背景:
这道题调了近
4
h
4h
4h,脑子废了…
题目传送门:
https://www.luogu.org/problemnew/show/P3224
题意:
n
n
n个点,每个点一个权值两种操作。
1.
1.
1.合并两个岛。
2.
2.
2.询问当前联通块的权值的第
k
k
k小值所对应的岛屿。
思路:
S
p
l
a
y
Splay
Splay+启发式合并。
细节较多(比如
f
a
,
s
i
z
e
fa,size
fa,size的初值,
r
o
o
t
root
root的处理等),可以仔细找找。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int bianhao,d,fa,c,son[2];} tr[200010];
int root[200010];
int fa[200010],size[200010];
int n,m,q,len;
inline int read()
{
int x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
return x*f;
}
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void ups(int x)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
tr[x].c=tr[lc].c+tr[rc].c+1;
}
void add(int bianhao,int d,int fa)
{
tr[++len]=(node){bianhao,d,fa,1,0,0};
}
void ins(int id,int bianhao,int d)
{
root[id]=id;
add(bianhao,d,0);
}
void rot(int x,int w)//左旋:0,右旋:1
{
int y=tr[x].fa,yy=tr[y].fa;
tr[y].son[1^w]=tr[x].son[w];
if(tr[x].son[w]) tr[tr[x].son[w]].fa=y;
tr[yy].son[tr[yy].son[0]==y?0:1]=x;
tr[x].fa=yy,tr[x].son[w]=y,tr[y].fa=x;
ups(y),ups(x);
}
void splay(int id,int x,int rt)
{
while(tr[x].fa!=rt)
{
int y=tr[x].fa,yy=tr[y].fa;
if(yy==rt)
{
rot(x,tr[y].son[0]==x?1:0);
continue;
}
if(tr[yy].son[0]==y)
{
if(tr[y].son[0]==x) rot(y,1),rot(x,1); else rot(x,0),rot(x,1);
continue;
}
if(tr[y].son[1]==x) rot(y,0),rot(x,0); else rot(x,1),rot(x,0);
}
if(!rt) root[id]=x;
}
int findip(int x,int d)
{
if(d==tr[x].d) return x;
if(d<tr[x].d)
return tr[x].son[0]?findip(tr[x].son[0],d):x;
else
return tr[x].son[1]?findip(tr[x].son[1],d):x;
}
int findnum(int x,int d)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
if(tr[x].c<d) return -1;
if(d<=tr[lc].c) return findnum(lc,d);
else if(d>tr[lc].c+1) return findnum(rc,d-tr[lc].c-1);
else return tr[x].bianhao;
}
void dfs(int x,int id)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
if(lc) dfs(lc,id);
int u=findip(root[id],tr[x].d);
tr[x].son[0]=tr[x].son[1]=0;
tr[x].fa=u;
tr[x].c=1;
tr[u].son[tr[x].d<tr[u].d?0:1]=x;
ups(u);
splay(id,x,0);
if(rc) dfs(rc,id);
}
void merge(int x,int y)
{
int t1=find(x),t2=find(y);
if(t1==t2) return;
if(size[t1]<size[t2]) swap(t1,t2);
dfs(root[t2],t1);
size[t1]+=size[t2];
fa[t2]=t1;
}
int main()
{
char s[5];
int x,y;
n=read(),m=read();
for(int i=1;i<=n;i++)
fa[i]=i,size[i]=1;
for(int i=1;i<=n;i++)
{
x=read();
ins(i,i,x);
}
for(int i=1;i<=m;i++)
{
x=read(),y=read();
merge(x,y);
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%s",s+1);
x=read(),y=read();
if(s[1]=='B') merge(x,y); else printf("%d\n",findnum(root[find(x)],y));
}
}