这样的圆应该不会太多。
1.学会了二分取左右边界的方法,记得要取min和max防止越界。
2.学会了一种新的线段树的写法,父节点并不完全包含子节点,相反地,父节点拥有的元素,子节点不会再拥有。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 1e2;
struct Oper {
int t, x, y, px, lx, rx;
Oper() {}
Oper(int t, int x, int y): t(t), x(x), y(y) {}
} oper[MAXN + 5];
#define lt ls,l,m
#define rt rs,m+1,r
#define ls (o<<1)
#define rs (o<<1|1)
set<int> st[MAXN * 4 + 5];
void Update(int o, int l, int r, int ql, int qr, int id, int d) {
if((ql <= l && r <= qr)) {
if(d == 1)
st[o].insert(id);
else
st[o].erase(id);
return;
} else {
int m = l + r >> 1;
if(ql <= m)
Update(lt, ql, qr, id, d);
if(qr >= m + 1)
Update(rt, ql, qr, id, d);
}
}
int QueryHelp(int o, int id) {
int px = oper[id].x, py = oper[id].y;
for(auto si : st[o]) {
int x = oper[si].x, y = oper[si].y;
if(1ll * (x - px) * (x - px) + 1ll * (y - py) * (y - py) < 1ll * y * y)
return si;
}
return -1;
}
int Query(int o, int l, int r, int id, int x) {
int res = QueryHelp(o, id);
if(l == r || res != -1)
return res;
int m = l + r >> 1;
if(x <= m)
return Query(lt, id, x);
else
return Query(rt, id, x);
}
int px[MAXN + 5], xtop;
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
scanf("%d", &n);
xtop = 0;
for(int i = 1; i <= n; ++i) {
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
px[++xtop] = x;
oper[i] = Oper(t, x, y);
}
sort(px + 1, px + 1 + xtop);
xtop = unique(px + 1, px + 1 + xtop) - (px + 1);
for(int i = 1; i <= n; ++i)
oper[i].px = lower_bound(px + 1, px + 1 + xtop, oper[i].x) - px;
for(int i = 1; i <= n; ++i) {
if(oper[i].t == 1) {
int lx = (oper[i].x - oper[i].y), rx = (oper[i].x + oper[i].y);
lx = min(xtop, upper_bound(px + 1, px + 1 + xtop, lx) - px);
rx = max(1, (lower_bound(px + 1, px + 1 + xtop, rx) - px) - 1);
oper[i].lx = lx, oper[i].rx = rx;
Update(1, 1, xtop, lx, rx, i, 1);
} else {
int res = Query(1, 1, xtop, i, oper[i].px);
printf("%d\n", res);
if(res != -1)
Update(1, 1, xtop, oper[res].lx, oper[res].rx, res, -1);
}
}
}