初始给定一个n个点m条边的无向图,q次操作,每次要么新增一条边,要么查询与某个点相连的所有点里点权第K小的点的编号。
查询联通分量容易想到并查集,查询第K大需要用平衡树,容易想到每个联通分量维护一棵平衡树,
每次新增加一条边对联通分量的影响就是合并两颗平衡树,为了保障复杂度正确,我们采用启发式合并,每次把小的联通分量的每个值暴力插到大的联通分量中,
简单来看,启发式合并一次,容量至少对小的联通分量来说是翻倍,再加上插入平衡树的均摊复杂度是O(logn)的,乍一看复杂度是O(nlog^2n)的
(不过camp讲课的时候说,把小的Splay的每个数值从小到大插入到大的Splay中,时间复杂度是O(nlogn)的,证明需要用到Dynamic Finger Theorem)
然后,貌似就做完了
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5;
const int INF=0x3f3f3f3f;
typedef long long ll;
struct Splay
{
int ch[2];
int fa;
int cnt,val,sz;
}b[maxn+5];
int father[maxn+5];
int tot=0,root[maxn+5];
inline int newNode(int fa,int val)
{
int p=++tot;
b[p].fa=fa;
b[p].val=val;
b[p].cnt=b[p].sz=1;
if (fa) b[fa].ch[b[fa].val<val]=p;
b[p].ch[0]=b[p].ch[1]=0;
return p;
}
inline int checkR(int p)
{
return b[b[p].fa].ch[1]==p;
}
inline void pushup(int p)
{
b[p].sz=b[p].cnt;
if (b[p].ch[0]) b[p].sz+=b[b[p].ch[0]].sz;
if (b[p].ch[1]) b[p].sz+=b[b[p].ch[1]].sz;
}
inline void RotateNode(int p)
{
int f=b[p].fa,ff=b[f].fa,w=checkR(p);
b[f].ch[w]=b[p].ch[w^1]; b[b[f].ch[w]].fa=f;
b[f].fa=p; b[p].ch[w^1]=f;
b[p].fa=ff;
if (ff) b[ff].ch[b[ff].ch[1]==f]=p;
pushup(f); pushup(p);
}
inline void SplayNode(int p,int goal,int q) //把p旋转为goal的儿子
{
while (b[p].fa!=goal) {
int f=b[p].fa;
int ff=b[f].fa;
if (ff!=goal) {
if (checkR(p)==checkR(f)) RotateNode(f);
else RotateNode(p);
}
RotateNode(p);
}
if (goal==0) root[q]=p;
}
inline void InsertNode(int val,int q)
{
int u=root[q],fa=0;
while (u) {
if (b[u].val==val) {
b[u].cnt++; pushup(u); SplayNode(u,0,q); return ;
}
fa=u;
u=b[u].ch[b[u].val<val];
}
u=newNode(fa,val); SplayNode(u,0,q);
}
inline int getVal(int rk,int q)
{
int u=root[q];
while (u) {
if (rk<=b[b[u].ch[0]].sz) u=b[u].ch[0];
else if (rk<=b[b[u].ch[0]].sz+b[u].cnt) {
SplayNode(u,0,q);
break;
}
else {
rk-=(b[b[u].ch[0]].sz+b[u].cnt);
u=b[u].ch[1];
}
}
return b[u].val;
}
int _find(int x)
{
if (x==father[x]) return x;
father[x]=_find(father[x]);
return father[x];
}
void dfs(int p,int to)
{
if (b[p].ch[0]) dfs(b[p].ch[0],to);
InsertNode(b[p].val,to);
if (b[p].ch[1]) dfs(b[p].ch[1],to);
}
void dfsSplay(int u)
{
printf("%d ",b[u].val);
if (b[u].ch[0]) dfsSplay(b[u].ch[0]);
if (b[u].ch[1]) dfsSplay(b[u].ch[1]);
}
void _merge(int u,int v)
{
u=_find(u); v=_find(v);
if (u==v) return ;
if (b[root[u]].sz>b[root[v]].sz) swap(u,v);
father[u]=v;
dfs(root[u],v);
}
char s[10];
int n,m,q,x,y;
int a[maxn+5],mp[maxn+5];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) father[i]=i;
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]); mp[a[i]]=i;
}
for (int i=1;i<=n;i++) InsertNode(a[i],i);
//for (int i=1;i<=n;i++) printf("%d %d %d\n",i,root[i],b[root[i]].val);
while (m--) {
scanf("%d%d",&x,&y);
_merge(x,y);
}
scanf("%d",&q);
while (q--) {
scanf("%s",s);
scanf("%d%d",&x,&y);
if (s[0]=='B') {
_merge(x,y);
}
else {
int u=_find(x);
if (b[root[u]].sz<y) printf("-1\n");
else printf("%d\n",mp[getVal(y,u)]);
}
}
return 0;
}
来源:https://www.cnblogs.com/xyw5vplus1/p/12229769.html