rt。我使用的是类似第一篇题解的维护方格并在当前圆最大半径小于方格边长二分之一时重构的方法。结果TLE。求指出我那里写假了,thx!
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN = 300005;
const ll MINN = -1e9;
int n, T, cnt = 0, tot, ans[MAXN];
ll R, maxR, N, M, b[MAXN], c[MAXN], x[MAXN], y[MAXN];
int mx[15] = {0, -1, -1, -1, 0, 1, 1, 1, 0}, my[15] = {-1, -1, 0, 1, 1, 1, 0, -1, 0};
struct node {
ll x, y, r, id;
bool operator <(const node &b) {
if (r != b.r) return r > b.r;
else return id < b.id;
}
} a[MAXN];
struct cir {
ll r, id;
bool operator < (const cir b) const{
if (r != b.r) return r > b.r;
else return id < b.id;
}
};
set<cir> s;
vector<cir> Round[MAXN];
inline void solve() {
R = maxR;
N = 0, M = 0, cnt = 0;
ll minn1 = -1e9, minn2 = -1e9;
auto now = *s.begin();
ll ox = a[now.id].x - now.r, oy = a[now.id].y - now.r;
for (int i = 1; i <= n; i++) {
if (ans[i]) continue;
x[i] = floor(1.0 * (a[i].x - ox) / (2 * R)) + 1, y[i] = floor(1.0 * (a[i].y - oy) / (2 * R)) + 1;
N = max(N, x[i]), M = max(M, y[i]);
minn1 = min(minn1, x[i]), minn2 = min(minn2, y[i]);
}
N -= minn1, M -= minn2;
for (int i = 1; i <= n; i++) {
if (ans[i]) continue;
b[++cnt] = N * (y[i] - 1) + x[i];
}
sort(b + 1, b + cnt + 1);
cnt = unique(b + 1, b + cnt + 1) - b - 1;
for (int i = 1; i <= n; i++) {
if (ans[i]) continue;
int way = lower_bound(b + 1, b + cnt + 1, N * (y[i] - 1) + x[i]) - b;
c[i] = way;
cir now = {a[i].r, i};
Round[c[i]].push_back(now);
}
}
inline void del(int k) {
T--;
cir now = {a[k].r, a[k].id};
//cout << k << endl;
s.erase(lower_bound(s.begin(), s.end(), now));
}
inline ll dis(ll ax, ll ay, ll bx, ll by) {return (ax - bx) * (ax - bx) + (ay - by) * (ay - by);}
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) {
a[i].x = read(), a[i].y = read(), a[i].r = read(), a[i].id = i, R = max(R, a[i].r);
cir now = {a[i].r, a[i].id};
s.insert(now);
}
T = n;
while (T) {
tot = 0;
auto now = *s.begin();
auto A = a[now.id];
maxR = now.r;
if (T == n || maxR <= R / 2) solve();
ll X = x[now.id], Y = y[now.id];
for (int i = 0; i <= 8; i++) {
vector<cir> g;
ll nx = X + mx[i], ny = Y + my[i];
ll query = N * (ny - 1) + nx;
int way = lower_bound(b + 1, b + cnt + 1, query) - b;
if (b[way] != query) continue;
//cout << way << " " << Round[way].size() << endl;
for (auto nxt: Round[way]) {
node v = a[nxt.id];
if (ans[v.id]) continue;
if (dis(v.x, v.y, A.x, A.y) <= (v.r + A.r) * (v.r + A.r)) ans[v.id] = A.id, del(v.id);
else g.push_back(nxt);
}
swap(g, Round[way]);
}
}
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}