题目描述
题解
比较裸的splay+启发式合并,暴力地将小的拆了插入到大的里面去就可以了。每一个集合可以用并查集来合并。
注意暴力拆的时候要做一个中序遍历,因为如果自顶向下拆的话有些父子关系会打破,这样就无法继续进行了。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e5+5;
int n,m,q,x,y,fx,fy,k,ans;
int belong[max_n],ch[max_n][2],f[max_n],size[max_n],root[max_n],key[max_n];
inline int find(int x){if (x==belong[x]) return x;else return belong[x]=find(belong[x]);}
inline int get(int x){return ch[f[x]][1]==x;}
inline void update(int x){
if (x){
size[x]=1;
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
inline void rotate(int x){
int old=f[x],oldf=f[old],which=get(x);
ch[old][which]=ch[x][which^1]; f[ch[old][which]]=old;
ch[x][which^1]=old; f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x; f[x]=oldf;
update(old);
update(x);
}
inline void splay(int x,int to){
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate((get(x)==get(fa))?fa:x);
root[to]=x;
}
inline void insert(int sz,int x,int to){
if (!root[to]){root[to]=sz;f[sz]=ch[sz][0]=ch[sz][1]=0;size[sz]=1;return;}
int now=root[to],fa=0;
while (1){
fa=now;
now=ch[now][x>key[now]];
if (!now){
f[sz]=fa; ch[sz][0]=ch[sz][1]=0;
size[sz]=1;
ch[fa][x>key[fa]]=sz;
update(sz); update(fa); splay(sz,to);
return;
}
}
}
inline void distroy(int now,int to){
if (ch[now][0]) distroy(ch[now][0],to);
if (ch[now][1]) distroy(ch[now][1],to);
insert(now,key[now],to);
}
inline int query(int root,int k){
int now=root;
while (1){
if (ch[now][0]&&size[ch[now][0]]>=k) now=ch[now][0];
else{
int temp=1;
if (ch[now][0]) temp+=size[ch[now][0]];
if (temp==k) return now;
k-=temp; now=ch[now][1];
}
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&key[i]),belong[i]=root[i]=i,f[i]=ch[i][0]=ch[i][1]=0,size[i]=1;
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
fx=find(x); fy=find(y); if (fx==fy) continue;
if (size[root[fx]]>size[root[fy]]) swap(x,y),swap(fx,fy);
distroy(root[fx],fy); belong[fx]=fy;
}
scanf("%d",&q);
for (int i=1;i<=q;++i){
char opt=getchar();
while (opt!='B'&&opt!='Q') opt=getchar();
if (opt=='B'){
scanf("%d%d",&x,&y);
fx=find(x); fy=find(y); if (fx==fy) continue;
if (size[root[fx]]>size[root[fy]]) swap(x,y),swap(fx,fy);
distroy(root[fx],fy); belong[fx]=fy;
}
else{
scanf("%d%d",&x,&k); fx=find(x);
if (k>size[root[fx]]) {printf("-1\n");continue;}
ans=query(root[fx],k);
printf("%d\n",ans);
}
}
}
总结
因为一个莫须有的错误调了一会不过1A嘿嘿嘿