其實就是一個小根堆啦,STL就能夠解決,可是擁有閒情雅緻的我學習了Jelly_Goat的左偏樹,增長了代碼長度,妙啊node
STL 裏面priority_queue默認是大根堆,修改一下變成小根堆ios
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } int n,opr,x; priority_queue<int,vector<int> ,greater<int> >h; int main() { n=read(); while(n--) { opr=read(); switch(opr) { case 1 : x=read();h.push(x);break; case 2 : printf("%d\n",h.top() );break; case 3 : h.pop() ;break; default : break ; } } return 0; }
什麼是左偏樹呢?spa
就是一個相似二叉堆的東西,畫出來像一個二叉樹3d
1.咱們定一個節點的 distance 爲他距離本身子樹中最右邊節點的距離,下面簡稱 dist code
因此,沒有右兒子的節點dist就是0啦blog
2.規定左偏樹中,對於一個節點來講,他的左兒子的dist > 他的右兒子的distget
而後這棵樹總體就左偏啦string
3.怎麼計算dist???it
dfs跑一遍???
其實也就是 dist [ fa ] = dist [ rson ] + 1
由於獲得一個節點的dist必定是與他的右兒子有關的,既然以前知道了右兒子的dist,從右兒子轉移過來,也就是dist [ rson ] + 1 ,不就獲得本身的dist了嗎
1.merge 合併操做
咱們在用左偏樹實現小根堆(大根堆也能夠實現)
假設咱們要合併兩個小左偏樹 a,b
(1)若是一個爲空,直接返回另外一個不就好啦
(2)若是兩個都不爲空,那麼咱們就把他們的根節點權值較小的一個做爲合併後的根節點,若是兩個根節點的權值同樣,那麼就把dist較大的一個做爲新根節點
(3)而後繼續往下面合併,假設新根是a,那麼把b合併到他的右子樹去,而後繼續處理a的左右子樹
(4)get一下新根的dist
2.insert 插入操做
get一個新的點,而後把他與原來的左偏樹合併
3.top 訪問堆頂 (左偏樹實現小/大根堆)
若是堆不爲空,就輸出堆頂元素,不然輸出0
4.pop 彈出堆頂
也就是把左偏樹的根節點去掉,合併他的左右子樹
5.size 記錄一共多少個元素
int cnt 記錄,每次新加一個點 就cnt++,彈出一個點,就cnt--
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=1e6+10; struct Heapnode { int lson=0,rson=0,val=0,dist=0; }; struct Heap { Heapnode tree[maxn]; int cnt=0,tot=0,rt=0; inline int New(int val) { ++tot; tree[tot].val=val; return tot; } inline int set_dist(int a) { return tree[a].rson ? tree[tree[a].rson].dist+1 : 0; } int merge(int a,int b) { if(a==0||b==0) return a+b; else if(tree[a].val>tree[b].val) swap(a,b); else if(tree[a].val==tree[b].val&&tree[a].dist<tree[b].dist) swap(a,b); tree[a].rson=merge(tree[a].rson,b); if(tree[a].lson!=0&&tree[a].rson!=0){ if(tree[tree[a].lson].dist<tree[tree[a].rson].dist) swap(tree[a].lson,tree[a].rson); } else if(tree[a].lson==0&&tree[a].rson!=0) swap(tree[a].lson,tree[b].rson); set_dist(a); return a; } inline void insert(int val) { cnt++; int b=New(val); rt=merge(rt,b); } inline int top() { return rt?tree[rt].val:0; } inline void pop() { cnt--; int a=tree[rt].lson,b=tree[rt].rson; rt=merge(a,b); } inline int size() { return cnt; } }h; int n,opr,x; int main() { n=read(); while(n--) { opr=read(); switch(opr) { case 1 : x=read();h.insert(x);break; case 2 : printf("%d\n",h.top() );break; case 3 : h.pop() ;break; default : break ; } } return 0; }