[bzoj 2733][HNOI2012]永无乡

传送门

Description

永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。

Solution

THUWC的前一天。。。

表示自己太菜什么都不会

打一道Splay的裸题压压惊

就是按照每个联通块建一个平衡树,然后就都是简单的操作辣

那么,就算是陪考,也加油咯


Code 

#include<bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define MN 100005
class SplayTree
{
    private: 
        int c[MN][2],siz[MN],a[MN],fa[MN],root[MN];
        inline bool get(int x) {return c[fa[x]][1]==x;}
        inline void up(int x){siz[x]=siz[c[x][1]]+siz[c[x][0]]+1;}
        inline void rotate(int x)
        {
            int y=fa[x],z=fa[y],l=get(x),r=l^1;
            if(z) c[z][get(y)]=x;
            fa[x]=z;c[y][l]=c[x][r];fa[c[x][r]]=y;c[x][r]=y;fa[y]=x;up(y);
        }
        inline void Splay(int x,int f,int &rt)
        {
            for(;fa[x]!=f;rotate(x))
                if(fa[fa[x]]!=f) rotate(get(x)^get(fa[x])?x:fa[x]);
            if(!f) rt=x;
			up(x);
        }
        inline int find(int x,int k)
        {
            if(k>siz[x]) return -1;
            if(k<=siz[c[x][0]]) return find(c[x][0],k);
            if(k>siz[c[x][0]]+1) return find(c[x][1],k-1-siz[c[x][0]]);
            return x;
        }
        inline void Insert(int &x,int id)
        {
            register int p=x;
            for(;c[p][a[id]>a[p]];p=c[p][a[id]>a[p]]);
            fa[id]=p;c[p][a[id]>a[p]]=id;siz[id]=1;c[id][0]=c[id][1]=0;
            Splay(id,0,x);
        }
        inline void dfs_merge(int x,int y)
        {
        	if(!x) return;
            if(c[x][0]) dfs_merge(c[x][0],y);
            if(c[x][0]) dfs_merge(c[x][1],y);
            Insert(root[y],x);
        }
    public:
        inline void Merge(int x,int y)
        {
        	if(!x||!y) return;
            Splay(x,0,root[x]);Splay(y,0,root[y]);
            if(siz[x]>siz[y]) std::swap(x,y);
            dfs_merge(x,y);
        }
        inline void init(int x,int val){a[x]=val;root[x]=x;siz[x]=1;fa[x]=c[x][0]=c[x][1]=0;}
        inline void Find(int x,int k){printf("%d\n",find(root[x],k));}
}T;
int bel[MN];
inline int getf(int x){return bel[x]==x?x:bel[x]=getf(bel[x]);}
int main()
{
    register int i,j,n,m,q;
    register char s[5];
    n=read();m=read();
    
    for(i=1;i<=n;++i) bel[i]=i,T.init(i,read());
    while(m--) i=read(),j=read(),T.Merge(i=getf(i),j=getf(j)),bel[i]=j;
    q=read();
    
    while(q--)
    {
        scanf("%s",s);
        if(s[0]=='Q')
        {
            i=read();
            T.Find(getf(i),read());
        }
        else
        {
            i=getf(read());j=getf(read());
            if(i!=j) T.Merge(i,j),bel[i]=j;
        }
    }
    return 0;
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-01-20 21:15  PaperCloud  阅读(150)  评论(0编辑  收藏  举报