題意:合併堆及刪除堆中最小元素。
思路:採用一般的二叉堆可以實現刪除操作,但是要合併的話就會爆,因此引進了左偏樹這個資料結構,可在logn時間內實現合併操作。
左偏樹的性質:
1.堆的性質
2.左子節點的距離大於右子節點的距離
正是利用這些性質實現堆的快速合併。
**如下:
(其中並查集的路徑壓縮會破壞掉樹的結構,因此在路徑壓縮後要將所有相鄰節點的父節點都置為當前的根節點)
#include#include#includeusing namespace std;
#define maxn 100050
int n,m;
int val[maxn],f[maxn],dis[maxn],ls[maxn],rs[maxn];
bool vis[maxn];
inline void ini()
//並查集的時候使用;
memset(vis,false,sizeof(vis));
memset(ls,0,sizeof(ls));//0表示為空節點;
memset(rs,0,sizeof(rs));
}int merge(int x,int y)
//其中一棵樹為空的時候的處理;
if((val[x]>val[y])||(val[x]==val[y]&&x>y))
//按照小根堆的方式,將權值大的樹並到權值小的樹的右子樹上;
rs[x]=merge(rs[x],y);//遞迴方式繼續合併;
if(dis[ls[x]]f[ls[x]]=f[rs[x]]=f[x]=x;
if(rs[x]==0)
else
return x;
}int del(int x)//刪除根節點;
int find(int x)//並查集;
int main()
for(i=1;i<=m;i++)
int fa=find(a);
int fb=find(b);
if(fa!=fb)
} else
int fa=find(a);
printf("%d\n",val[fa]);
del(fa);
} }
return 0;
}
洛谷 P3377 模板 左偏樹
題目描述 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 ...
P3377 左偏樹,模板)
題意 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 1並...
洛谷P3377 模板 左偏樹(可並堆)
題目描述 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 ...