【Splay】BZOJ 2773-永无乡
依旧是数据结构...之前玩的不够爽,本来想去写一发维修数列,后面想了想还是算了...
Splay还是比较好玩的,这道题要用到的是Splay的启发式合并...
具体说来,用并查集维护连通性,然后每次合并两块Splay的时候将小的那棵Splay一个个拆下来插入到大的那一棵上。
理论上每个点只会有一次插入,所以在复杂度允许的范围内。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #define lch t[x].s[0] 6 #define rch t[x].s[1] 7 #define maxn 105000 8 using namespace std; 9 10 struct node { int s[2],key,f,size,num; } t[maxn]; 11 int i,j,n,m,k,a,b; 12 int f[maxn],s[maxn]; 13 14 void update(int x) { t[lch].f = t[rch].f = x; t[x].size = t[lch].size + t[rch].size + 1; } 15 void clear(int x) { t[x].s[0] = t[x].s[1] = t[x].f = t[x].key = t[x].size = 0; } 16 17 void Rou(int x,bool kind) 18 { 19 int v = t[x].s[!kind]; t[x].s[!kind] = t[v].s[kind]; t[v].s[kind] = x; 20 t[v].f = t[x].f; t[x].f = v; t[t[x].s[!kind]].f = x; 21 22 t[t[v].f].s[x == t[t[v].f].s[1]] = v; 23 update(x); update(v); 24 25 clear(0); 26 } 27 28 int find(int x,int k) 29 { 30 if (t[lch].size == k-1) return x; 31 else if (t[lch].size > k-1) return find(lch,k); 32 else return find(rch,k-1-t[lch].size); 33 } 34 35 #define R(x) Rou( t[(x)].f,t[t[(x)].f].s[0] == (x) ) 36 37 void splay(int x,int f) { while (t[x].f != f) R(x); } 38 39 void insert(node now,int x) 40 { 41 t[x].size++; 42 if (now.key < t[x].key) 43 if (!lch) lch = now.num,t[lch] = now,t[lch].size = 1,t[lch].f = x; 44 else insert(now,lch); 45 else 46 if (!rch) rch = now.num,t[rch] = now,t[rch].size = 1,t[rch].f = x; 47 else insert(now,rch); 48 } 49 50 void travel(int x,int root) 51 { 52 if (lch) travel(lch,root),lch = 0; 53 if (rch) travel(rch,root),rch = 0; 54 insert(t[x],root); 55 } 56 57 int getf(int x) 58 { 59 if (f[x] != x) return f[x] = getf(f[x]); 60 return f[x]; 61 } 62 63 void work(int a,int b) 64 { 65 int r1 = getf(a), r2 = getf(b); 66 if (r1 == r2) return; 67 68 if (s[r1] > s[r2]) swap(r1,r2); 69 f[r1] = r2; s[r2] += s[r1]; s[r1] = 0; 70 splay(r2,0); splay(r1,0); 71 72 travel(r1,r2); 73 } 74 75 int main() 76 { 77 scanf("%d %d",&n,&m); 78 for (i = 1; i <= n; i++) 79 scanf("%d",&t[i].key),f[i] = i,s[i] = 1,t[i].num = i,t[i].size = 1; 80 81 for (i = 1; i <= m; i++) 82 { 83 scanf("%d %d",&a,&b); 84 work(a,b); 85 } 86 87 int q,x,y; char ch; 88 scanf("%d\n",&q); 89 while (q--) 90 { 91 scanf("%c %d %d\n",&ch,&x,&y); 92 93 if (ch == 'B') work(x,y); 94 if (ch == 'Q') 95 { 96 int root = getf(x); 97 splay(root,0); 98 if (t[root].size < y) printf("-1\n"); 99 else printf("%d\n",find(root,y)); 100 } 101 } 102 103 return 0; 104 }
posted on 2015-01-24 10:22 MMMoonLighttt 阅读(166) 评论(0) 编辑 收藏 举报