P3224 [HNOI2012]永无乡
思路
平衡树+启发式合并
貌似也可以线段树合并
连边就是合并两个Treap,查询就是第k大
使用Treap,好写好调
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int Nodecnt=0,root[100100*2],fa[100100*2],n,m,w_p[100100*2];
struct Node{
int lson,rson,sz,val,ran,num;
}Treap[100100*2];
int find(int x){
if(fa[x]==x)
return x;
else
return fa[x]=find(fa[x]);
}
queue<int> q;
void throwin(int x){
q.push(x);
}
int getnew(int val,int num){
int o;
if(q.size())
o=q.front(),q.pop();
else
o=++Nodecnt;
Treap[o].lson=Treap[o].rson=0;
Treap[o].sz=1;
Treap[o].ran=rand();
Treap[o].val=val;
Treap[o].num=num;
return o;
}
void pushup(int o){
Treap[o].sz=Treap[Treap[o].lson].sz+Treap[Treap[o].rson].sz+1;
}
void rorateL(int &o){
int x=Treap[o].rson;
Treap[o].rson=Treap[x].lson;
Treap[x].lson=o;
pushup(o);
pushup(x);
o=x;
}
void rorateR(int &o){
int x=Treap[o].lson;
Treap[o].lson=Treap[x].rson;
Treap[x].rson=o;
pushup(o);
pushup(x);
o=x;
}
void insert(int val,int num,int &o){
if(!o){
o=getnew(val,num);
return;
}
Treap[o].sz++;
if(val<=Treap[o].val){
insert(val,num,Treap[o].lson);
if(Treap[Treap[o].lson].ran<Treap[o].ran)
rorateR(o);
}
else{
insert(val,num,Treap[o].rson);
if(Treap[Treap[o].rson].ran<Treap[o].ran)
rorateL(o);
}
}
int query(int val,int o){
if(!o)
return -1;
if(val==Treap[Treap[o].lson].sz+1)
return Treap[o].num;
else if(val>Treap[Treap[o].lson].sz+1)
return query(val-Treap[Treap[o].lson].sz-1,Treap[o].rson);
else
return query(val,Treap[o].lson);
}
void dfs(int &o,int to){
if(!o)
return;
insert(Treap[o].val,Treap[o].num,root[to]);
dfs(Treap[o].lson,to);
dfs(Treap[o].rson,to);
throwin(o);
o=0;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w_p[i]),fa[i]=i,insert(w_p[i],i,root[i]);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d %d",&a,&b);
if(find(a)!=find(b)){
if(Treap[find(a)].sz<Treap[find(b)].sz){
dfs(root[find(a)],find(b));
fa[find(a)]=find(b);
}
else{
dfs(root[find(b)],find(a));
fa[find(b)]=find(a);
}
}
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
char opt=getchar();
while(opt!='B'&&opt!='Q')
opt=getchar();
int a,b;
scanf("%d %d",&a,&b);
if(opt=='B'){
if(find(a)!=find(b)){
if(Treap[find(a)].sz<Treap[find(b)].sz){
dfs(root[find(a)],find(b));
fa[find(a)]=find(b);
}
else{
dfs(root[find(b)],find(a));
fa[find(b)]=find(a);
}
}
}
else{
printf("%d\n",query(b,root[find(a)]));
}
}
return 0;
}