P3377-[模板]左偏树(可并堆)
生活随笔
收集整理的這篇文章主要介紹了
P3377-[模板]左偏树(可并堆)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P3377
題目大意
開始時(shí)nnn個(gè)只有一個(gè)數(shù)的集合,要求支持
解題思路
左偏樹就是維護(hù)一個(gè)滿足以下性質(zhì)的樹
每次合并時(shí)我們只需要將valvalval小的合并到valvalval大的右子樹上,然后每次合并完之后就判斷左右兩邊的深度大小。
時(shí)間復(fù)雜度O(nlog?n)O(n\log n)O(nlogn)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10; int n,m,val[N]; struct Left_tree{int dis[N],fa[N],t[N][2];int Merge(int x,int y){if(!x||!y) return x+y;if(val[x]>val[y]||(val[x]==val[y]&&x>y))swap(x,y);int &ls=t[x][0],&rs=t[x][1];rs=Merge(rs,y);if(dis[ls]<dis[rs]) swap(ls,rs);fa[rs]=fa[ls]=x;dis[x]=dis[rs]+1;return x;}void Del(int x){int ls=t[x][0],rs=t[x][1];fa[ls]=ls;fa[rs]=rs;val[x]=-1;fa[x]=Merge(ls,rs);}int Get(int x){return (fa[x]==x)?(x):(fa[x]=Get(fa[x]));} }T; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&val[i]),T.fa[i]=i;while(m--){int op,x,y;scanf("%d%d",&op,&x);if(op==1){scanf("%d",&y);if(val[x]==-1||val[y]==-1)continue;x=T.Get(x);y=T.Get(y);T.Merge(x,y);}if(op==2){if(val[x]==-1){printf("-1\n");continue;}x=T.Get(x);printf("%d\n",val[x]);T.Del(x);}} }總結(jié)
以上是生活随笔為你收集整理的P3377-[模板]左偏树(可并堆)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jzoj6451-[2020.01.19
- 下一篇: 联盟电脑配置要求高吗(联盟电脑配置要求)