bzoj2733[HNOI2012]永无乡

bzoj2733[HNOI2012]永无乡

题意:

n个节点,每个节点有个权值,初始时有m次连通两点的操作,接下来有q次操作,每次可以连通两个点或求某个点所在连通块权值第k小的节点编号。n,m≤100000,q≤300000

题解:

treap启发式合并,就是暴力将小的树拆了插到大的树里,均摊复杂度O(log22n)。由于本弱用的是treap,不能维护fa数组,所以要并查集维护根节点。如果是splay就不用。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdlib>
 5 #include <queue>
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 #define maxn 100500
 8 using namespace std;
 9 
10 int fa[maxn],rt[maxn],ch[maxn][2],v[maxn],sz[maxn],rnd[maxn];
11 void update(int x){
12     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
13 }
14 void rot(int &x,bool lr){
15     if(!x)return; int a=ch[x][lr]; ch[x][lr]=ch[a][!lr]; ch[a][!lr]=x;
16     update(x); update(a); x=a; 
17 }
18 void insert(int &x,int y){
19     if(!x){x=y; return;}
20     if(v[y]<v[x])insert(ch[x][0],y);else insert(ch[x][1],y); update(x);
21     if(ch[x][0]&&rnd[ch[x][0]]<rnd[x])rot(x,0);
22     if(ch[x][1]&&rnd[ch[x][1]]<rnd[x])rot(x,1);
23 }
24 int find(int x,int k){
25     if(sz[x]<k)return -1;
26     if(sz[ch[x][0]]==k-1)return x;
27     if(sz[ch[x][0]]<k-1)return find(ch[x][1],k-sz[ch[x][0]]-1);
28     if(sz[ch[x][0]]>k-1)return find(ch[x][0],k);
29 }
30 queue <int> q;
31 int fd(int x){return x==fa[x]?x:fa[x]=fd(fa[x]);}
32 void merge(int xx,int yy){
33     int x=fd(xx),y=fd(yy); if(x==y)return; if(sz[rt[x]]>sz[rt[y]])swap(x,y);
34     fa[x]=y; while(! q.empty())q.pop(); q.push(rt[x]); y=rt[y];
35     while(! q.empty()){
36         int z=q.front(); q.pop(); sz[z]=1;
37         if(ch[z][0])q.push(ch[z][0]); if(ch[z][1])q.push(ch[z][1]);
38         ch[z][0]=ch[z][1]=0; insert(y,z);
39     }
40     rt[fa[x]]=y;
41 }
42 inline int read(){
43     char ch=getchar(); int f=1,x=0;
44     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
45     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
46     return f*x;
47 }
48 int n,m;
49 int main(){
50     n=read(); m=read();
51     inc(i,1,n)
52         v[i]=read(),ch[i][0]=ch[i][1]=0,rnd[i]=rand(),fa[i]=rt[i]=i,sz[i]=1;
53     inc(i,1,m){int a=read(),b=read(); merge(a,b);}
54     m=read(); char opt[3];
55     inc(i,1,m){
56         scanf("%s",opt);
57         if(opt[0]=='Q'){
58             int a=read(),b=read(); printf("%d\n",find(rt[fd(a)],b));
59         }
60         if(opt[0]=='B'){
61             int a=read(),b=read(); merge(a,b);
62         }
63     }
64     return 0;
65 }

 

20160608

posted @ 2016-08-16 22:48  YuanZiming  阅读(177)  评论(0编辑  收藏  举报