题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失,
每次射击找出哪个靶子被射中,或者没有射中靶子。
思路:关键点在于,圆都与x轴相切,那么我们能发现,如果射击在(x, y) 这个点,包含它的圆只可能是它左边第一个直径>= y的圆c1,
或者是它右边第一个直径 >=y 的圆c2,因为在c1 和 c2之间的圆不可能覆盖到(x, y), 因为它们的直径小于y,在c1左边和c2右边的圆
通过画图我们也能得出不肯能包含(x, y),那么每次射击我们只需要check两个圆就好了。
找圆的过程能用线段树维护,加入一个圆就在线段树对应的x的位置的值变成2*r,然后通过二分用线段树找圆,最后判一下是否在圆内。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 2e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, tot, mx[N << 2], X[N], hs[N]; struct Qus { int op, x, y; } qus[N]; void update(int pos, int v, int l, int r, int rt) { if(l == r) { mx[rt] = v; return; } int mid = l + r >> 1; if(pos <= mid) update(pos, v, l, mid, rt << 1); else update(pos, v, mid + 1, r, rt << 1 | 1); mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); } int getMx(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return mx[rt]; int mid = l + r >> 1, ans = 0; if(L <= mid) ans = max(ans, getMx(L, R, l, mid, rt << 1)); if(R > mid) ans = max(ans, getMx(L, R, mid + 1, r, rt << 1 | 1)); return ans; } bool check(int x, int y, int id) { LL dis1 = 1ll * qus[id].y * qus[id].y; LL dis2 = 1ll * (x - qus[id].x) * (x - qus[id].x) + 1ll * (y - qus[id].y) * (y - qus[id].y); return dis1 > dis2; } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d%d", &qus[i].op, &qus[i].x, &qus[i].y); hs[++tot] = qus[i].x; } sort(hs + 1, hs + 1 + tot); tot = unique(hs + 1, hs + 1 + tot) - hs - 1; for(int i = 1; i <= n; i++) { int op = qus[i].op, x = qus[i].x, y = qus[i].y; int pos = lower_bound(hs + 1, hs + 1 + tot, x) - hs; if(op == 1) { X[pos] = i; update(pos, 2 * y, 1, tot, 1); } else { int l = 1, r = pos, ret = -1; while(l <= r) { int mid = l + r >> 1; if(getMx(mid, pos, 1, tot, 1) >= y) ret = mid, l = mid + 1; else r = mid - 1; } if(ret != -1 && check(x, y, X[ret])) { printf("%d\n", X[ret]); update(ret, 0, 1, tot, 1); continue; } l = pos, r = tot, ret = -1; while(l <= r) { int mid = l + r >> 1; if(getMx(pos, mid, 1, tot, 1) >= y) ret = mid, r = mid - 1; else l = mid + 1; } if(ret != -1 && check(x, y, X[ret])) { printf("%d\n", X[ret]); update(ret, 0, 1, tot, 1); continue; } puts("-1"); } } return 0; }