这道题调了近 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
#include
#include
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));
}
}