不得不说
现在真的是越来越懒了
很多东西都咕咕咕了啊
qwq
还是回到这个题
首先,涉及到联通块第
k
k
k大的问题,有两种方法来解决,这里只介绍
s
p
l
a
y
splay
splay
(我果然是已经菜到 s p l a y splay splay都不会了
首先对于每一个点建一个
s
p
l
a
y
splay
splay并加入两个哨兵节点。然后对于题目的连边操作,我们选择进行启发式合并,就是每次合并的是,通过遍历
s
i
z
e
size
size较小的那个
s
p
l
a
y
splay
splay,把里面的节点依次删掉,然后插到
s
i
z
e
size
size大的那个
s
p
l
a
y
splay
splay里面。
不过编号的处理似乎并不是很好的处理
我选择的处理方式是,每一个点的在 s p l a y splay splay的节点编号就是他自身的编号,然后插入的时候,我们只会插入那些有用的节点,也就是非哨兵节点
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define mk make_pair
#define pb push_back
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 4e5+1e2;
const int inf = 1e9;
int root[maxn];
int a[maxn];
int n,m;
int ch[maxn][2];
int size[maxn];
int tot;
int fa[maxn];
int val[maxn];
vector<int> rb;
int num[maxn];
int newnode()
{
int now=0;
if(rb.empty()) ++tot,now=tot;
else now = rb.back(),rb.pop_back();
return now;
}
int delnode(int x)
{
//rb.push_back(x);
fa[x]=ch[x][1]=ch[x][0]=size[x]=0;
}
int son(int x)
{
if(ch[fa[x]][0]==x) return 0;
else return 1;
}
void update(int x)
{
size[x]=size[ch[x][1]]+size[ch[x][0]]+1;
}
void rotate(int x)
{
int y = fa[x],z=fa[y];
int b = son(x),c = son(y);
ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
}
void splay(int x,int p)
{
while (fa[x]!=p)
{
int y = fa[x],z = fa[y];
if (z==p) rotate(x);
else
{
if(son(x)==son(y))
{
rotate(y);
rotate(x);
}
else
{
rotate(x);
rotate(x);
}
}
}
if (p==0) root[x]=x;
}
int find_qq(int root,int x)
{
int now = root;
int num=0;
while(now)
{
if (val[now]<x)
{
num = now;
now = ch[now][1];
}
else
now = ch[now][0];
}
return num;
}
int find_hj(int root,int x)
{
int now = root;
int num=0;
while (now)
{
if (val[now]>x)
{
num = now;
now = ch[now][0];
}
else
now = ch[now][1];
}
return num;
}
void insert(int root,int x,int p)
{
int qq = find_qq(root,x);
int hj = find_hj(root,x);
splay(qq,0);
splay(hj,qq);
int y = ch[hj][0];
int uu = p;
fa[uu]=hj;
ch[hj][0]=uu;
size[uu]=1;
val[uu]=x;
splay(uu,0);
}
void delet(int root,int x)
{
int qq = find_qq(root,x);
int hj = find_hj(root,x);
splay(qq,0);
splay(hj,qq);
int y = ch[hj][0];
delnode(y);
num[y]=0;
ch[hj][0]=0;
}
int kth(int root,int x)
{
int now = root;
while (1)
{
if (x<=size[ch[now][0]]) now = ch[now][0];
else
{
if (x<=size[ch[now][0]]+1) return now;
x-=size[ch[now][0]]+1;
now=ch[now][1];
}
}
}
int faa[maxn];
int b[maxn];
int tmp;
int find(int x)
{
if(faa[x]!=x) faa[x]=find(faa[x]);
return faa[x];
}
void dfs(int x)
{
if(x<=n) b[++tmp]=x;
if (ch[x][0]) dfs(ch[x][0]);
if (ch[x][1]) dfs(ch[x][1]);
//cout<<1<<endl;
}
void merge(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if (f1==f2) return;
faa[f1]=faa[f2];
splay(x,0);
splay(y,0);
//cout<<1<<endl;
if(size[x]>size[y]) swap(x,y);
tmp=0;
dfs(x);
for (int i=1;i<=tmp;i++) delnode(b[i]);
for (int i=1;i<=tmp;i++) insert(root[y],a[b[i]],b[i]);
}
int main()
{
n=read(),m=read();
tot=n;
for (int i=1;i<=n;i++)
{
root[i]=++tot;
val[tot]=inf;
size[tot]=1;
int pre = tot;
++tot;
size[tot]=1;
val[tot]=-inf;
fa[tot]=pre;
ch[pre][0]=tot;
}
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++) faa[i]=i;
for (int i=1;i<=n;i++) insert(root[i],a[i],i),splay(i,0);
for (int i=1;i<=m;i++)
{
int x=read(),y=read();
merge(x,y);
}
//for (int i=1;i<=n;i++) cout<<root[i]<<" "<<val[kth(root[i],2)]<<endl;
//cout<<endl;
int q=read();
for (int i=1;i<=q;i++)
{
char s[10];
scanf("%s",s+1);
int x=read(),y=read();
if (s[1]=='Q')
{
splay(x,0);
y++;
if (y>size[x]-1) cout<<-1<<"\n";
else cout<<kth(root[x],y)<<"\n";
}
else
{
merge(x,y);
}
}
return 0;
}