P3378 【模板】堆 (內含左偏樹實現)

P3378 【模板】堆

 

 

題解

其實就是一個小根堆啦,STL就能夠解決,可是擁有閒情雅緻的我學習了Jelly_Goat的左偏樹,增長了代碼長度,妙啊node

 

Solution 1 STL

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;
}

 

 

 

Solution 2 左偏樹

安利 Jelly_Goat 神仙的blog學習

什麼是左偏樹呢?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;
}
相關文章
相關標籤/搜索