左偏树模板
看大佬们的博客吧QwQ
https://www.cnblogs.com/yyf0309/p/LeftistTree.html
https://www.luogu.org/blog/cytus/ke-bing-dui-zhi-zuo-pian-shu
我就放一下代码就好了
以下删除皆为顶点
删除特定节点什么的以后会补充的
嗯……
维护一颗左偏的二叉树,以及并查集,最主要的是可并
#include<bits/stdc++.h> #define re return #define ll long long #define inc(i,l,r) for(register int i=l;i<=r;++i) const int maxn=100005; using namespace std; char buf[1<<21],*p1,*p2; inline int gc(){re p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=gc())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=gc())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,fa[maxn],val[maxn],ls[maxn],rs[maxn],dist[maxn]; inline int find(int x) { re x==fa[x]?x:fa[x]=find(fa[x]); } //合并x,y; inline int merge(int x,int y) { if(!x||!y)re x+y; //将现存子树根节点,接在上一个节点的右子树 if(val[x]>val[y]||(val[x]==val[y]&&x>=y)) x^=y^=x^=y; //维护小根堆性质,根节点是最小的 rs[x]=merge(rs[x],y); //递归合并 fa[rs[x]]=x; //维护新的右子树fa值 if(dist[ls[x]]<dist[rs[x]])swap(ls[x],rs[x]); //维护左偏 dist[x]=dist[rs[x]]+1; re x; } int main() { rd(n),rd(m); inc(i,1,n) { fa[i]=i; rd(val[i]); } dist[0]=-1; //如果右子树为0,则根节点高度为0 int opt,x,y; inc(i,1,m) { rd(opt); if(opt==1) { rd(x),rd(y); //如果没有这个数,或者已经同在一个堆里,则跳过 if(val[x]==-1||val[y]==-1)continue; x=find(x);y=find(y); if(x==y)continue; merge(x,y); } else { rd(x); if(val[x]==-1) printf("-1\n"); else { x=find(x); printf("%d\n",val[x]); val[x]=-1; int v=merge(ls[x],rs[x]); fa[v]=fa[x]=v;//防止find压缩路径出锅 } } } re 0; }