Description
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
对于 20%的数据 n≤1000,q≤1000
对于 100%的数据 n≤100000,m≤n,q≤300000
如果该岛屿不存在,则输出-1。
Solution
求第k大可以用主席树或者是各种平衡树,考虑到要合并就上splay+启发式合并就行了。需要注意的是输出的是原本点的编号,这个要记录一下
用并查集维护联通块,查询的时候查询一个splay内的第k大,合并的时候把size较小的暴力插进size较大的
救酱
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=2000005;
struct treeNode {int son[2],fa,key,size,bel;} t[N];
std:: vector <int> rec[N];
int root[N],f[N],tot;
int a[N];
void new_node(int scc,int &x,int fa,int key,int bel) {
t[x=++tot]=(treeNode) {{0,0},fa,key,1,bel};
rec[scc].push_back(tot);
}
void push_up(int x) {
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
}
void rotate(int x) {
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[z].son[t[z].son[1]==y]=x; t[x].fa=z;
t[y].son[k]=t[x].son[!k]; t[t[x].son[!k]].fa=y;
t[x].son[!k]=y; t[y].fa=x;
push_up(y); push_up(x);
}
void splay(int x,int &root) {
while (t[x].fa) {
int y=t[x].fa; int z=t[y].fa;
if (z) {
if ((t[z].son[1]==y)^(t[y].son[1]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
root=x;
}
void insert(int scc,int key,int bel) {
int now=root[scc],tmp=0;
while (now) tmp=now,now=t[now].son[key>t[now].key];
new_node(scc,t[tmp].son[key>t[tmp].key],tmp,key,bel);
splay(tot,root[scc]);
}
int kth(int x,int k) {
if (t[x].size<k) return -1;
while (233) {
if (t[t[x].son[0]].size+1==k) return t[x].bel;
if (t[t[x].son[0]].size>=k) x=t[x].son[0];
else k-=t[t[x].son[0]].size+1,x=t[x].son[1];
}
}
int get_father(int x) {
if (f[x]==x) return x;
f[x]=get_father(f[x]);
return f[x];
}
bool merge(int x,int y) {
x=get_father(x); y=get_father(y);
if (x==y) return false;
if (t[root[x]].size>t[root[y]].size) std:: swap(x,y);
rep(i,0,rec[x].size()-1) {
insert(y,t[rec[x][i]].key,t[rec[x][i]].bel);
rec[y].push_back(rec[x][i]);
}
f[x]=y;
return true;
}
int main(void) {
int n,m; scanf("%d%d",&n,&m);
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,n) new_node(i,root[i],0,a[i],i);
rep(i,1,n) f[i]=i;
rep(i,1,m) {
int x,y; scanf("%d%d",&x,&y);
merge(x,y);
}
int T; scanf("%d",&T);
while (T--) {
char opt[2]; scanf("%s",opt);
int x,y; scanf("%d%d",&x,&y);
if (opt[0]=='B') {
merge(x,y);
} else if (opt[0]=='Q') {
int fx=get_father(x);
int ans=kth(root[fx],y);
printf("%d\n", ans);
}
}
return 0;
}