题意:平面上有N个子弹,每个子弹的坐标已知,现在在距离点x0,y0为R的圆内,所以的子弹都会变成冰块L*L,并且在L*L范围内的所有其他子弹也会变成冰块,问,当连锁反应结束时,变成冰块的子弹数有多少。
也就是说落在子弹L/2的范围内的子弹都会结冰,也可以转化成只要边界在子弹L/4范围内的子弹会结冰,这样扫描线就可以搞定了。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; typedef long long LL; const int N=100005; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) struct Line { LL x,y1,y2,w; Line(){} Line(LL x,LL y1,LL y2,LL w) : x(x),y1(y1),y2(y2),w(w) {} bool operator<(const Line &B)const { return x<B.x||(x==B.x&&w>B.w); } }; int n,R,L,len; int fa[N],cnt[N],vis[N]; LL X[N],Y[N],x0,y0; vector<LL> SY; map<LL,int> H; vector<Line> line; LL sqr(LL x) { return x*x; } int find_fa(int x) { if(fa[x]==x) return x; return fa[x]=find_fa(fa[x]); } void unin(int a,int b) { int x=find_fa(a); int y=find_fa(b); if(x!=y) fa[x]=y,cnt[y]+=cnt[x]; } struct SegTree { int color[N*4]; void build(int lft,int rht,int ind) { color[ind]=0; if(lft!=rht) { int mid=MID(lft,rht); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int st,int ed,int valu,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) { if(valu>0) color[ind]=valu; else if(color[ind]==-valu) color[ind]=0; } else { int mid=MID(lft,rht); if(st<=mid) updata(st,ed,valu,lft,mid,LL(ind)); if(ed> mid) updata(st,ed,valu,mid+1,rht,RR(ind)); } } int query(int pos,int lft,int rht,int ind) { if(color[ind]!=0) return color[ind]; if(lft==rht) return 0; int mid=MID(lft,rht); if(pos<=mid) return query(pos,lft,mid,LL(ind)); else return query(pos,mid+1,rht,RR(ind)); } }seg; int main() { while(scanf("%d%d%d",&n,&R,&L)!=EOF) { line.clear(); SY.clear(); H.clear(); for(int i=0;i<N;i++) fa[i]=i,cnt[i]=1,vis[i]=0; for(int i=1;i<=n;i++) { LL a,b; scanf("%lld%lld",&a,&b); X[i]=a; Y[i]=b; SY.push_back(b*4-L); SY.push_back(b*4+L); line.push_back(Line(a*4-L,b*4-L,b*4+L,i)); line.push_back(Line(a*4+L,b*4-L,b*4+L,-i)); } sort(line.begin(),line.end()); sort(SY.begin(),SY.end()); SY.erase(unique(SY.begin(),SY.end()),SY.end()); len=(int)SY.size(); for(int i=0;i<len;i++) H[SY[i]]=i; seg.build(0,len-1,1); for(int i=0;i<(int)line.size();i++) { int y1=H[line[i].y1]; int y2=H[line[i].y2]; int w=line[i].w; if(w>0) { int tmp1=seg.query(y1,0,len-1,1); int tmp2=seg.query(y2,0,len-1,1); if(tmp1!=0) unin(tmp1,w); if(tmp2!=0) unin(tmp2,w); } seg.updata(y1,y2,w,0,len-1,1); } scanf("%lld%lld",&x0,&y0); int res=0; for(int i=1;i<=n;i++) { LL tmp1=sqr(X[i]-x0); LL tmp2=sqr(Y[i]-y0); if(tmp1+tmp2<=sqr(R)&&vis[find_fa(i)]==0) { vis[find_fa(i)]=1; res+=cnt[find_fa(i)]; } } printf("%d\n",res); } return 0; }