【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 }
BZOJ 2773

 

posted on 2015-01-24 10:22  MMMoonLighttt  阅读(165)  评论(0编辑  收藏  举报

导航