左偏树(可并堆)【模板】 发表于 2017-07-06 是洛谷上面的那道模板题啦 合并的本身就是利用递归不断维护感觉有了合并很多操作都很方便了很好的一篇论文下面的代码只有删除与合并的操作 一切尽在code中领会 CODE123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;int fa[101010],l[101010],r[101010];int s[101010],dis[101010],die[101010];int n,m;inline void read(int &x){ int data=0,w=1; char ch=0; while (ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if (ch=='-') w=-1,ch=getchar(); while (ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar(); x=data*w;}int merge(int x,int y){ if (x==0) return y; if (y==0) return x; if (s[x]>s[y] || s[x]==s[y]&&(x>y)) swap(x,y); r[x]=merge(r[x],y); if (dis[r[x]]>dis[l[x]]) swap(r[x],l[x]); dis[x]=dis[r[x]]+1; return x;} void change(int x,int y){ fa[x]=y; if (l[x]) change(l[x],y); if (r[x]) change(r[x],y);}void del(int x){ printf("%d\n",s[x]); die[x]=1; x=merge(l[x],r[x]); change(x,x);} int main(){ dis[0]=-1; read(n); read(m); for (int i=1;i<=n;++i) { read(s[i]); fa[i]=i; } int x,y,t; for (int i=1;i<=m;++i) { read(t); if (t==1) { read(x); read(y); if (die[x] || die[y] || fa[x]==fa[y]) continue; x=fa[x]; y=fa[y]; x=merge(x,y); change(x,x); } else { read(x); if (die[x]) printf("-1\n"); else del(fa[x]); } } return 0;} --------------------------