左偏树
更推荐启发式合并,好写多了
主要是这个可以持久化
#include<bits/stdc++.h>
#define F(i0,i1,i2) for(int i0=(i1);i0<=(i2);++i0)
#define fr first
#define sc second
#define int long long
#define pii pair<int,int>
using namespace std;
inline int rd(){
int x=0,f=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return f?-x:x;
}
const int N=1e5+7,mod=998244353,inf=1ll<<60;
int n,m;
struct Node{
int v,rt,d;
int rs,ls;
}tr[N];
int fnd(int x){return tr[x].rt==x?x:tr[x].rt=fnd(tr[x].rt);}
int mer(int x,int y){
if(!x||!y)return x|y;
if(tr[x].v>tr[y].v||(tr[x].v==tr[y].v&&x>y))swap(x,y);//后面的这半部分是因为要先删除编号小的节点
tr[x].rs=mer(tr[x].rs,y);
if(tr[tr[x].rs].d>tr[tr[x].ls].d)swap(tr[x].ls,tr[x].rs);//保证左偏
tr[x].rt=tr[tr[x].ls].rt=tr[tr[x].rs].rt=x;
tr[x].d=tr[tr[x].rs].d+1;
return x;
}
int del[N];
void pop(int x){
tr[x].v=-1;//废除节点
tr[tr[x].ls].rt=tr[x].ls;
tr[tr[x].rs].rt=tr[x].rs;
tr[x].rt=mer(tr[x].ls,tr[x].rs);
}
signed main(){
n=rd(),m=rd();
F(i,1,n)tr[i].v=rd(),tr[i].rt=i;
while(m--){
int op=rd();
if(op==1){
int x=rd(),y=rd();
if(tr[x].v==-1||tr[y].v==-1)continue;
int fx=fnd(x),fy=fnd(y);
if(fx!=fy)tr[fx].rt=tr[fy].rt=mer(fx,fy);
}
else {
int x=rd();
if(tr[x].v==-1){
cout<<-1<<'\n';
continue;
}
cout<<tr[fnd(x)].v<<'\n';
pop(fnd(x));
}
}
return 0;
}

浙公网安备 33010602011771号