【Luogu】P3224永无乡(splay)

  题目链接

  splay模板,启发式合并(其实就是暴力插入)即可。

  顺便吐槽时限,带垃圾回收而已……不至于最后一个点死活不让过吧?

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<queue>
#define maxn 100020
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int CNT;
struct Node{
    int val,size,e[2],fa,num;
}tree[maxn*10];
int tot;

struct Splay{
    int root;
    Splay(){root=0;}
    inline void update(int x){tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1;    }
    inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
    inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
    void rotate(int x){
        int y=tree[x].fa;    int r=tree[y].fa;
        int sony=iden(x);    int sonr=iden(y);
        if(root==y)    root=x;
        int b=tree[x].e[sony^1];
        connect(b,y,sony);
        connect(y,x,sony^1);
        connect(x,r,sonr);
        update(y);    update(x);
    }
    void splay(int pos,int to){
        to=tree[to].fa;
        while(tree[pos].fa!=to){
            if(tree[tree[pos].fa].fa==to)    rotate(pos);
            else
                if(iden(pos)==iden(tree[pos].fa)){
                    rotate(tree[pos].fa);
                    rotate(pos);
                }
                else{    rotate(pos);    rotate(pos);    }
        }
    }
    inline int create(int val,int num,int fa){
        tree[++tot]=(Node){val,1,{0,0},fa,num};
        return tot;
    }
    int build(int val,int num){
        if(root==0){
            root=create(val,num,0);
            return root;
        }
        int now=root;
        while(now){
            tree[now].size++;
            int nxt=val<tree[now].val?0:1;
            if(tree[now].e[nxt]==0){
                connect(create(val,num,now),now,nxt);
                update(now);
                return tot;
            }
            now=tree[now].e[nxt];
        }
    }
    void insert(int val,int num){
        int p=build(val,num);
        if(++CNT==50){
            splay(p,root);
            CNT=0;
        }
    }
    int rank(int val){
        if(tree[root].size<val)    return -1;
        int now=root;
        while(1){
            if(tree[tree[now].e[0]].size+1==val)    return tree[now].num;
            if(tree[tree[now].e[0]].size>=val)    now=tree[now].e[0];
            else{
                val-=tree[tree[now].e[0]].size+1;
                now=tree[now].e[1];
            }
        }
    }
}s[maxn];

void pushtree(int now,int x){
    s[x].insert(tree[now].val,tree[now].num);
    if(tree[now].e[0])    pushtree(tree[now].e[0],x);
    if(tree[now].e[1])    pushtree(tree[now].e[1],x);
}

int father[maxn];
int w[maxn];

int ufind(int x){
    if(father[x]!=x)    father[x]=ufind(father[x]);
    return father[x];
}

void unionn(int x,int y){
    x=ufind(x);    y=ufind(y);
    if(tree[s[x].root].size<tree[s[y].root].size)    swap(x,y);
    pushtree(s[y].root,x);
    father[y]=x;
}

int main(){
    int n=read(),m=read();
    for(int i=1;i<=n;++i){
        w[i]=read();
        father[i]=i;
        s[i].insert(w[i],i);
    }
    for(int i=1;i<=m;++i){
        int x=read(),y=read();
        unionn(x,y);
    }
    int p=read();
    for(int i=1;i<=p;++i){
        char c[10];
        scanf("%s",c);
        int x=read(),y=read();
        if(c[0]=='Q')    printf("%d
",s[ufind(x)].rank(y));
        else            unionn(x,y);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/8358187.html