【LG4631】[APIO2018]Circle selection 選圓圈
阿新 • • 發佈:2018-12-30
【LG4631】[APIO2018]Circle selection 選圓圈
題面
題解
用\(kdt\)亂搞剪枝。
維護每個圓在\(x、y\)軸的座標範圍
相當於維護一個矩形的座標範圍為\([x-r,x+r],[y-r,y+r]\)
可以減小搜尋範圍
然後再判斷一下一個圓是否在當前搜尋的矩形內,不在就剪枝
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (!isdigit(ch) && ch != '-') ch = getchar(); if (ch == '-') w = -1, ch = getchar(); while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); return w * data; } void chkmin(int &x, int y) { if (x > y) x = y; } void chkmax(int &x, int y) { if (x < y) x = y; } #define sqr(x) (1ll * (x) * (x)) const int MAX_N = 3e5 + 10; struct Point { int x[2], r, id; } p[MAX_N]; struct Node { int mn[2], mx[2], ls, rs; Point tp; } t[MAX_N]; int N, WD, rt, ans[MAX_N], rub[MAX_N], cur, top; inline bool operator < (const Point &l, const Point &r) { return l.x[WD] < r.x[WD]; } inline bool cmp(const Point &l, const Point &r) { return (l.r == r.r) ? (l.id < r.id) : (l.r > r.r); } int newnode() { if (top) return rub[top--]; else return ++cur; } void pushup(int o) { int ls = t[o].ls, rs = t[o].rs; for (int i = 0; i <= 1; i++) { int r = t[o].tp.r; t[o].mx[i] = t[o].tp.x[i] + r; t[o].mn[i] = t[o].tp.x[i] - r; if (ls) chkmax(t[o].mx[i], t[ls].mx[i]), chkmin(t[o].mn[i], t[ls].mn[i]); if (rs) chkmax(t[o].mx[i], t[rs].mx[i]), chkmin(t[o].mn[i], t[rs].mn[i]); } } int build(int l, int r, int wd) { if (l > r) return 0; int mid = (l + r) >> 1, o = newnode(); WD = wd, nth_element(&p[l], &p[mid], &p[r + 1]), t[o].tp = p[mid]; t[o].ls = build(l, mid - 1, wd ^ 1), t[o].rs = build(mid + 1, r, wd ^ 1); return pushup(o), o; } bool chk1(int o, Point tmp) { return sqr(tmp.x[0] - t[o].tp.x[0]) + sqr(tmp.x[1] - t[o].tp.x[1]) <= sqr(tmp.r + t[o].tp.r); } bool chk2(int o, Point tmp) { int x0 = tmp.x[0], x1 = tmp.x[1], r = tmp.r; if (x0 + r < t[o].mn[0]) return 1; if (x0 - r > t[o].mx[0]) return 1; if (x1 + r < t[o].mn[1]) return 1; if (x1 - r > t[o].mx[1]) return 1; return 0; } void query(int o, Point tmp) { if (chk2(o, tmp)) return ; if (!ans[t[o].tp.id] && chk1(o, tmp)) ans[t[o].tp.id] = tmp.id; if (t[o].ls) query(t[o].ls, tmp); if (t[o].rs) query(t[o].rs, tmp); } int main () { N = gi(); for (int i = 1; i <= N; i++) p[i].x[0] = gi(), p[i].x[1] = gi(), p[i].r = gi(), p[i].id = i; rt = build(1, N, 0); sort(p + 1, p + N + 1, cmp); for (int i = 1; i <= N; i++) if (!ans[p[i].id]) query(rt, p[i]); for (int i = 1; i <= N; i++) printf("%d ", ans[i]); printf("\n"); return 0; }