[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!
致虚极,守静笃,万物并作,吾以观其复