当前位置: 代码迷 >> 综合 >> 【并查集】Baltic2016 Park
  详细解决方案

【并查集】Baltic2016 Park

热度:113   发布时间:2023-09-27 03:53:22.0

分析:

很简单的并查集水题。
每个圆视为一个点,上下左右四个边界各视为一个点,

两点间距离表示:最大能穿过的圆的直径。

所以可以先把n2n^2n2条边的预处理出来,然后再把边权从小到大排序,询问的圆也从小到大排序即可。

判断一下几个边界是否连通,就能知道它能到达哪些点。

只不过卡精度了很难受。。。

所以得用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;}elsel=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;
}