题意:平面上有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;
}