【模板】左偏树(可并堆) 可并堆_并查集
左偏树的树高是 $log(n)$ 级别的,所以在查询祖先的时候是不可以直接顺着左偏树上的父亲查询的.
另开一个并查集,在并查集上进行路径压缩的查询即可.
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 100006
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,m;
struct MHEAP{
int f[maxn],ch[maxn][2],val[maxn],dis[maxn];
int merge(int x,int y){
if(!x||!y) return x+y;
if(val[x]>val[y]||(val[x]==val[y]&&y<x)) swap(x,y);
ch[x][1]=merge(ch[x][1],y);
f[ch[x][1]]=f[ch[x][0]]=x;
if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][1],ch[x][0]);
dis[x]=dis[ch[x][1]]+1;
return x;
}
int getfa(int x)
{
return f[x]!=x ? f[x]=getfa(f[x]) : x;
}
void pop(int x)
{
f[ch[x][0]]=ch[x][0],f[ch[x][1]]=ch[x][1];
f[x]=merge(ch[x][0],ch[x][1]);
val[x]=-1;
}
void opt1(int x,int y)
{
if(val[x]==-1||val[y]==-1) return;
if(x==y) return ;
int a=getfa(x),b=getfa(y);
if(a==b) return ;
merge(a,b);
}
void opt2(int x)
{
if(val[x]==-1)
{
printf("-1\n");
return;
}
int a=getfa(x);
printf("%d\n",val[a]);
pop(a);
}
}T;
int main(){
//setIO("input");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&T.val[i]);
for(int i=1;i<=n;++i) T.f[i]=i;
for(int i=1,opt,a,b;i<=m;++i){
scanf("%d",&opt);
if(opt==1) scanf("%d%d",&a,&b),T.opt1(a,b);
if(opt==2) scanf("%d",&a),T.opt2(a);
}
return 0;
}