题目大意:
给你N台电脑和一个距离D,然后给你N台电脑的坐标xi,yi,0<=xi,yi<=10000,d<=20000,给你最多3e5次查询,每次查询中,(O x)表示修复了x号电脑,(S x y)表示询问x和y是否可以通信,返回查询结果(如果两台电脑距离在d之内,那么两台电脑可以相连)
题解:
一共3e5次查询,但是最多有1000个点,所以最多修复1000台电脑,枚举所有电脑,找到他周围可以连接的电脑,进行合并(一开始想的是,如果修复3e5次,直接时间爆炸,不过后来发现最多修1e3次,傻了。。。)给了10s,直接水过
不知道为啥我开始想的时候是在连接的时候就进行合并,然后修复的时候再找边,一定是失了智。。。
贴上代码:

1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #define mem(a,b) memeset(a,b,sizeof(b)) 5 using namespace std; 6 const int maxn=1e3+10; 7 int parent[maxn],vis[maxn],rank[maxn]; 8 int d,n; 9 struct node 10 { 11 int x,y; 12 node(){} 13 node(int a,int b):x(a),y(b){} 14 }pc[maxn]; 15 double len(node a,node b) 16 { 17 int x=a.x-b.x; 18 int y=a.y-b.y; 19 return sqrt(x*x+y*y); 20 } 21 int find(int x) 22 { 23 int k, j, r; 24 r = x; 25 while(r != parent[r]) 26 r = parent[r]; 27 k = x; 28 while(k != r) 29 { 30 j = parent[k]; 31 parent[k] = r; 32 k = j; 33 } 34 return r; 35 } 36 void merg(int x,int y) 37 { 38 int fx=find(x); 39 int fy=find(y); 40 if(rank[fx]<=rank[fy]) 41 { 42 parent[fy]=fx; 43 rank[fx]++; 44 } 45 else 46 { 47 parent[fx]=fy; 48 rank[fy]++; 49 } 50 } 51 void ini() 52 { 53 for(int i=1;i<=maxn;i++) parent[i]=i; 54 } 55 int main() 56 { 57 ini(); 58 scanf("%d%d",&n,&d); 59 for(int i=1;i<=n;i++) 60 { 61 scanf("%d%d",&pc[i].x,&pc[i].y); 62 } 63 char s; 64 while(cin>>s) 65 { 66 int a,b; 67 if(s=='O') 68 { 69 scanf("%d",&a); 70 if(vis[a]) continue; 71 vis[a]=1; 72 for(int i=1;i<=n;i++) 73 { 74 if(a==i) continue; 75 if(len(pc[a],pc[i])>d) continue; 76 if(!vis[i]) continue; 77 else merg(a,i); 78 } 79 /*for(int i=1;i<=n;i++) 80 { 81 printf("%d ",parent[i]); 82 }puts(" ");*/ 83 } 84 else 85 { 86 scanf("%d%d",&a,&b); 87 int fa=find(a); 88 int fb=find(b); 89 if(fa==fb) printf("SUCCESS "); 90 else printf("FAIL "); 91 } 92 } 93 return 0; 94 }