AtCoder Beginner Contest 234 Ex Enumerate Pairs

洛谷传送门

AtCoder 传送门

把每个点分到 \((\left\lfloor\frac{x}{K}\right\rfloor, \left\lfloor\frac{y}{K}\right\rfloor)\) 的正方形内,枚举相邻正方形,计入答案。

正确性显然。

复杂度证明就是所有每个正方形内距离为 \(K\) 的点对下界为 \(\Omega(n^2)\)。考虑分成四个边长为 \(\frac{K}{2}\) 的小正方形,显然每个小正方形内的点对都满足条件。根据抽屉原理,设四个小正方形内点数分别为 \(a \ge b \ge c \ge d\),则有 \(a \ge \frac{x}{4}\)\(x\) 为大正方形内的点数。那么大正方形内合法点对的下界为 \(\frac{a(a-1)}{2}\),这个是 \(O(n^2) = 4 \times 10^5\) 级别的。然后枚举相邻的正方形,均值不等式易得枚举的点对也是 \(O(n^2) = 4 \times 10^5\) 级别的。然后就做完了。

code
// Problem: Ex - Enumerate Pairs
// Contest: AtCoder - AtCoder Beginner Contest 234
// URL: https://atcoder.jp/contests/abc234/tasks/abc234_h
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

ll n, m;
pii a[maxn];
map< pii, vector<int> > mp;

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld%lld", &a[i].fst, &a[i].scd);
		mp[make_pair(a[i].fst / m, a[i].scd / m)].pb(i);
	}
	vector<pii> ans;
	for (int i = 1; i <= n; ++i) {
		for (int p = -1; p <= 1; ++p) {
			for (int q = -1; q <= 1; ++q) {
				for (int x : mp[make_pair(a[i].fst / m + p, a[i].scd / m + q)]) {
					if (i < x && (a[i].fst - a[x].fst) * (a[i].fst - a[x].fst) + (a[i].scd - a[x].scd) * (a[i].scd - a[x].scd) <= m * m) {
						ans.pb(i, x);
					}
				}
			}
		}
	}
	sort(ans.begin(), ans.end());
	printf("%d\n", (int)ans.size());
	for (pii p : ans) {
		printf("%lld %lld\n", p.fst, p.scd);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-05-11 10:01  zltzlt  阅读(17)  评论(0编辑  收藏  举报