题目链接:A Archery Tournament
题意:给出n个操作,操作1:新建一个圆形;操作2:给定一个坐标,查询该点是否在某个圆里,若在,输出标号同时消除这个圆(坐标的范围是-1e9~1e9)
题解:考虑将每个圆抽象化为一条线段,考虑到同时覆盖某节点的线段不会有很多,该题则转换为 询问点被哪几条线段覆盖,然后暴力判断即可
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int lson[20*N],rson[20*N]; set<int>v[20*N]; int x_[N],y_[N]; int root,cnt,ans; bool check(int x1,int y1,int x,int y){ return 1ll*(x1-x)*(x1-x)+1ll*(y1-y)*(y1-y)<1ll*y*y; } void insert(int x,int y,int l,int r,int &p,int id){ if(!p) p=++cnt; if(l>=x&&r<=y){v[p].insert(id);return;} int mid=(l+r)>>1; if(mid>=x) insert(x,y,l,mid,lson[p],id); if(mid<y) insert(x,y,mid+1,r,rson[p],id); } void query(int x,int y,int l,int r,int p){ if(!p) return; for(auto it:v[p]){ if(check(x,y,x_[it],y_[it])){ans=it;return;} } if(l==r) return; int mid=(l+r)>>1; if(x<=mid) query(x,y,l,mid,lson[p]); else query(x,y,mid+1,r,rson[p]); } void del(int x,int y,int l,int r,int p){ if(l>=x&&r<=y){v[p].erase(ans);return;} int mid=(l+r)>>1; if(mid>=x) del(x,y,l,mid,lson[p]); if(mid<y) del(x,y,mid+1,r,rson[p]); } int main(){ int n,cas;scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&cas); if(cas==1){ scanf("%d%d",&x_[i],&y_[i]); insert(x_[i]-y_[i],x_[i]+y_[i],-1e9,1e9,root,i); } else{ int a,b;ans=-1; scanf("%d%d",&a,&b); query(a,b,-1e9,1e9,root); printf("%d\n",ans); if(ans!=-1) del(x_[ans]-y_[ans],x_[ans]+y_[ans],-1e9,1e9,root); } } return 0; }