E - Most Brilliant Starry Sky 解説
by
sounansya
印刷ページ
(この解法は snuke さんの提案した解法です)
\((X_i,Y_i)\) に重み \(1\) 、\((-X_i,-Y_i)\) に重み \(0\) の点があるとして \(2N\) 個の点を偏角ソートすることを考えます。
このように重み \(0\) の頂点を仮想的に入れてソートすることで、本問題の答えは偏角ソート後の点列に含まれる長さ \(N\) の連続部分列(ただし円環として考える)に含まれる重み \(1\) の点の個数の最大値となります。
この解法は尺取り法が不要になるため、かなり簡単に実装することができます。
#include <bits/stdc++.h>
using namespace std;
struct Point {
long x, y;
int w;
};
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
int T;
cin >> T;
while (T--) {
int N;
cin >> N;
vector<Point> A;
for (int i = 0; i < N; i++) {
long x, y;
cin >> x >> y;
A.push_back({x, y, 1});
A.push_back({-x, -y, 0});
}
auto half = [](const Point &p) { return p.y > 0 || (p.y == 0 && p.x > 0); };
sort(A.begin(), A.end(), [&](const Point &a, const Point &b) {
if (half(a) != half(b)) return half(a) > half(b);
return a.x * b.y > a.y * b.x;
});
int sum = 0;
for (int i = 0; i < N; i++) sum += A[i].w;
int ans = sum;
for (int i = 0; i < 2 * N; i++) {
sum += A[(i + N) % (2 * N)].w - A[i].w;
ans = max(ans, sum);
}
cout << ans << '\n';
}
}
投稿日時:
最終更新:
