奇怪啊,怎么过不去呢,每次运行并查集的 merge 操作 就会寄,大概是treap启发式合并写挂了?我没看出来哪儿挂了
#include<bits/stdc++.h>
#include<chrono>
using namespace std;
mt19937 mt(chrono::system_clock::to_time_t(chrono::system_clock::now()));
const long long N=5e5+10;
int n,m,q;
struct treap{
int lc[N],rc[N],val[N],w[N],siz[N],id[N];
int root[N],cnt;
int newnode(int v,int i){
cnt++;
val[cnt]=v;
w[cnt]=(int)mt();
siz[cnt]=1;
id[cnt]=i;
}
void pushup(int x){
siz[x]=siz[lc[x]]+siz[rc[x]]+1;
}
void split(int x,int v,int &a,int &b){
if(!a||!b){
a=b=0;
return;
}
if(v>=val[x]){
b=x;
split(lc[x],v,a,lc[0]);
}else{
a=x;
split(rc[x],v,rc[x],b);
}
pushup(x);
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(w[x]<w[y]){
rc[x]=merge(rc[x],y);
pushup(x);
return x;
}else{
lc[y]=merge(x,lc[y]);
pushup(y);
return y;
}
}
void split2(int x,int k,int &a,int &b){
if(!x){
a=b=0;
return;
}
if(k<=siz[lc[x]]){
b=x;
split2(lc[x],k,a,lc[x]);
}else{
a=x;
split2(rc[x],k-siz[lc[x]]-1,rc[x],b);
}
pushup(x);
}
}fhq;
struct UFS{
int fa[N];
void init(){
for(int i=1;i<=n;i++) fa[i]=i;
}
int getfa(int x){
if(fa[x]==x) return x;
return fa[x]=getfa(fa[x]);
}
bool check(int &x,int &y){
x=getfa(x);
y=getfa(y);
return x==y;
}
void dfs(int x,int &y){
if(!x) return;
dfs(fhq.lc[x],y);
dfs(fhq.rc[x],y);
fhq.lc[x]=fhq.rc[x]=0;
fhq.siz[x]=1;
int t=fhq.val[x];
int rt1,rt2;
fhq.split(y,t,rt1,rt2);
y=fhq.merge(rt1,fhq.merge(x,rt2));
}
void merge(int x,int y){
if(check(x,y)) return;
if(fhq.siz[fhq.root[x]]>fhq.siz[fhq.root[y]]) swap(x,y);//这句话莫名其妙会寄
fa[x]=y;
dfs(fhq.root[x],fhq.root[y]);//这里也会寄
}
}ufs;
int main(){
cin>>n>>m;
ufs.init();
for(int i=1;i<=n;i++){
int x;
cin>>x;
fhq.root[i]=fhq.newnode(x,i);
}
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
ufs.merge(u,v);//就是这儿挂了
}
cin>>q;
for(int i=1;i<=q;i++){
char op;
int u,v;
cin>>op>>u>>v;
if(op=='Q'){
u=ufs.getfa(u);
if(fhq.siz[fhq.root[u]]<v){
cout<<"-1\n"; continue;
}
int t1,t2,t3;
fhq.split2(fhq.root[u],fhq.siz[fhq.root[u]]-v,t1,t2);
fhq.split2(t2,1,t2,t3);
cout<<fhq.id[t2]<<endl;
fhq.root[u]=fhq.merge(t1,fhq.merge(t2,t3));
}else{
ufs.merge(u,v);
}
}
}