zoukankan      html  css  js  c++  java
  • [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
    ",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!

  • 相关阅读:
    day5
    \_\_setitem\_\_和\_\_getitem和\_\_delitem__
    描述符(\_\_get\_\_和\_\_set\_\_和\_\_delete\_\_)
    \_\_getattribute\_\_
    面向对象进阶小结
    property装饰器
    super()方法详解
    菱形继承问题
    类的派生
    类的继承
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10296221.html
Copyright © 2011-2022 走看看