分析:
很简单的并查集水题。
每个圆视为一个点,上下左右四个边界各视为一个点,
两点间距离表示:最大能穿过的圆的直径。
所以可以先把 n 2 n^2 n2条边的预处理出来,然后再把边权从小到大排序,询问的圆也从小到大排序即可。
判断一下几个边界是否连通,就能知道它能到达哪些点。
只不过卡精度了很难受。。。
所以得用longlong二分适合的边权。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define SF scanf
#define PF printf
#define MAXN 3000010
#define EPS 1e-6
using namespace std;
typedef long long ll;
int fa[MAXN];
struct node{
int u,v;
ll val;
node () {}
node (int u1,int v1,double val1):u(u1),v(v1),val(val1) {}
bool operator <(const node &a) const {
if(val!=a.val)
return val<a.val;
if(u!=a.u)
return u<a.u;
return v<a.v;
}
}edge[MAXN];
struct cir{
int x,y,r;
bool operator <(const cir &a) const {
if(r!=a.r)
return r<a.r;
if(x!=a.x)
return x<a.x;
return y<a.y;
}
}p[MAXN],q[MAXN];
int get_fa(int x){
if(fa[x]==0)
return x;
fa[x]=get_fa(fa[x]);
return fa[x];
}
void merge(int u,int v){
u=get_fa(u);
v=get_fa(v);
if(u==v)
return ;
fa[u]=v;
}
bool check(int u,int v){
u=get_fa(u);
v=get_fa(v);
return u!=v;
}
bool check(int u,int v,ll len){
ll dx=p[u].x-p[v].x;
ll dy=p[u].y-p[v].y;
ll len1=dx*dx+dy*dy;
len=len+p[u].r+p[v].r;
return len1<len*len;
}
int n,m,w,h,tot;
ll find_dist(int u,int v){
ll l=0,r=max(w,h);
ll ans=r;
while(l!=r){
ll mid=(l+r)>>1;
if(check(u,v,mid)){
r=mid;
}
else
l=mid+1;
}
return l;
}
string ans[MAXN];
int main(){
SF("%d%d",&n,&m);
SF("%d%d",&w,&h);
for(int i=1;i<=n;i++)
SF("%d%d%d",&p[i].x,&p[i].y,&p[i].r);
for(int i=1;i<=m;i++){
SF("%d%d",&q[i].r,&q[i].x);
q[i].y=i;
}
int L=n+1,D=n+2,R=n+3,U=n+4;
for(int i=1;i<=n;i++){
edge[++tot]=node(i,L,p[i].x-p[i].r);
edge[++tot]=node(i,D,p[i].y-p[i].r);
edge[++tot]=node(i,R,w-p[i].x-p[i].r);
edge[++tot]=node(i,U,h-p[i].y-p[i].r);
for(int j=i+1;j<=n;j++)
edge[++tot]=node(i,j,find_dist(i,j));
}
sort(edge+1,edge+1+tot);
sort(q+1,q+1+m);
int top=1;
for(int i=1;i<=m;i++){
while(top<=tot&&edge[top].val <=2ll*q[i].r){
// PF("{%d %d %lf}\n",edge[top].u,edge[top].v,edge[top].val);
merge(edge[top].u,edge[top].v);
top++;
}
// PF("[%d %d %d %d]\n",i,q[i].x,q[i].r,q[i].y);
int id=q[i].x;
if(id==1){
ans[q[i].y]+='1';
if(check(D,R)&&check(D,U)&&check(L,D))
ans[q[i].y]+='2';
if(check(U,R)&&check(L,R)&&check(U,D)&&check(L,D))
ans[q[i].y]+='3';
if(check(L,U)&&check(L,R)&&check(L,D))
ans[q[i].y]+='4';
}
else if(id==2){
if(check(D,R)&&check(D,U)&&check(L,D))
ans[q[i].y]+='1';
ans[q[i].y]+='2';
if(check(D,R)&&check(L,R)&&check(U,R))
ans[q[i].y]+='3';
if(check(L,U)&&check(L,R)&&check(U,D)&&check(D,R))
ans[q[i].y]+='4';
}
else if(id==3){
if(check(U,R)&&check(L,R)&&check(U,D)&&check(L,D))
ans[q[i].y]+='1';
if(check(D,R)&&check(L,R)&&check(U,R))
ans[q[i].y]+='2';
ans[q[i].y]+='3';
if(check(U,R)&&check(U,D)&&check(U,L))
ans[q[i].y]+='4';
}
else if(id==4){
if(check(L,U)&&check(L,R)&&check(L,D))
ans[q[i].y]+='1';
if(check(L,U)&&check(L,R)&&check(U,D)&&check(R,D))
ans[q[i].y]+='2';
if(check(U,R)&&check(U,D)&&check(U,L))
ans[q[i].y]+='3';
ans[q[i].y]+='4';
}
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
}