码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2733[HNOI2012]永无乡

时间:2016-08-17 00:03:26      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

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 }

 

201608608

bzoj2733[HNOI2012]永无乡

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5778179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!