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
",query(b,root[find(a)]));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10710644.html