E - Most Brilliant Starry Sky 解説 by sounansya 印刷ページ


(この解法は snuke さんの提案した解法です)

\((X_i,Y_i)\) に重み \(1\) 、\((-X_i,-Y_i)\) に重み \(0\) の点があるとして \(2N\) 個の点を偏角ソートすることを考えます。

このように重み \(0\) の頂点を仮想的に入れてソートすることで、本問題の答えは偏角ソート後の点列に含まれる長さ \(N\) の連続部分列(ただし円環として考える)に含まれる重み \(1\) の点の個数の最大値となります。

この解法は尺取り法が不要になるため、かなり簡単に実装することができます。

実装例(C++)

#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';
	}
}

投稿日時:
最終更新: