[luogu3377]模板左偏树(可并堆)
Posted elpsycongroo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu3377]模板左偏树(可并堆)相关的知识,希望对你有一定的参考价值。
解题关键:左偏树模板
1、路径压缩版本
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=1e5+3; int n,m; struct tree{ int l,r; int dis,val,fa; }tr[N]; int Get(int x){return tr[x].fa==x?x:tr[x].fa=Get(tr[x].fa);} int Merge(int x,int y){ if(!x||!y)return x+y; if(tr[x].val>tr[y].val||(tr[x].val==tr[y].val&&x>y)) swap(x,y); int &ul=tr[x].l,&ur=tr[x].r; ur=Merge(ur,y); if(tr[ul].dis<tr[ur].dis)swap(ul,ur); tr[ur].fa=tr[ul].fa=x; tr[x].dis=tr[ur].dis+1; return x; } void Erase(int x){ int ul=tr[x].l,ur=tr[x].r; tr[x].val=-1;tr[ul].fa=ul;tr[ur].fa=ur; tr[x].fa=Merge(ul,ur); } int Del(int x){ int fx=tr[x].fa; int ka=Merge(tr[x].l,tr[x].r); tr[ka].fa=fx; int &ul=tr[fx].l,&ur=tr[fx].r; ul==x?ul=ka:ur=ka; while(fx){ if(tr[ul].dis<tr[ur].dis)swap(ul,ur); if(tr[fx].dis==tr[ur].dis+1) return Get(fx); tr[fx].dis=tr[ur].dis+1; ka=fx; fx=tr[x].fa; ul=tr[fx].l,ur=tr[fx].r; } return ka; } int Build(){ queue<int>q; for(int i=1;i<=n;i++) q.push(i); int x,y,z; while(q.size()>1){ x=q.front();q.pop(); y=q.front();q.pop(); z=Merge(x,y);q.push(z); } return q.front(); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)tr[i].fa=i,scanf("%d",&tr[i].val); for(int i=1,c,x,y;i<=m;i++){ scanf("%d",&c); if(c==1){ scanf("%d%d",&x,&y); if(tr[x].val==-1||tr[y].val==-1)continue; int nx=Get(x); int ny=Get(y); if(nx==ny) continue; Merge(nx,ny); }else{ scanf("%d",&x); if(tr[x].val==-1){ puts("-1"); }else{ y=Get(x); printf("%d ",tr[y].val); Erase(y); } } } return 0; }
2、非路径压缩版本,保留树结构
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=1e5+3; int n,m; struct tree{ int l,r; int dis,val,fa; }tr[N]; int Get(int x){ while(tr[x].fa)x=tr[x].fa; return x; } int Merge(int x,int y){ if(!x||!y)return x+y; if(tr[x].val>tr[y].val||(tr[x].val==tr[y].val&&x>y)) swap(x,y); int &ul=tr[x].l,&ur=tr[x].r; ur=Merge(ur,y); tr[ur].fa=x; if(tr[ul].dis<tr[ur].dis)swap(ul,ur); tr[x].dis=tr[ur].dis+1; return x; } void Erase(int x){ int ul=tr[x].l,ur=tr[x].r; tr[x].val=-1;tr[ul].fa=0;tr[ur].fa=0; Merge(ul,ur); } int Del(int x){ int fx=tr[x].fa; int ka=Merge(tr[x].l,tr[x].r); tr[ka].fa=fx; int &ul=tr[fx].l,&ur=tr[fx].r; ul==x?ul=ka:ur=ka; while(fx){ if(tr[ul].dis<tr[ur].dis)swap(ul,ur); if(tr[fx].dis==tr[ur].dis+1) return Get(fx); tr[fx].dis=tr[ur].dis+1; ka=fx; fx=tr[x].fa; ul=tr[fx].l,ur=tr[fx].r; } return ka; } int Build(){ queue<int>q; for(int i=1;i<=n;i++) q.push(i); int x,y,z; while(q.size()>1){ x=q.front();q.pop(); y=q.front();q.pop(); z=Merge(x,y);q.push(z); } return q.front(); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&tr[i].val); for(int i=1,c,x,y;i<=m;i++){ scanf("%d",&c); if(c==1){ scanf("%d%d",&x,&y); if(tr[x].val==-1||tr[y].val==-1)continue; int nx=Get(x); int ny=Get(y); if(nx==ny) continue; Merge(nx,ny); }else{ scanf("%d",&x); if(tr[x].val==-1){ puts("-1"); }else{ y=Get(x); printf("%d ",tr[y].val); Erase(y); } } } return 0; }
以上是关于[luogu3377]模板左偏树(可并堆)的主要内容,如果未能解决你的问题,请参考以下文章