Treap

POJ - 3481
警告:千萬不要初始化種子,這oj會RE被坑了一天QAQ。
Treap就是一個用隨機數優化了的二叉搜索樹,二叉搜索樹滿足某個節點的值大於等於左兒子節點的值,小於右兒子節點的值,但是這樣插入的值就會有可能形成一條鏈造成很低的效率,所以採用了用隨機數優化的方法,隨機的給每一個節點賦予一個優先級,在插入節點時,節點的優先級滿足堆的性質(小頂堆或大頂堆),值滿足二叉搜索樹的性質,這就是一顆Treap。

爲了滿足上述的兩個性質,在每次插入的時候都要對節點進行旋轉操作,因爲每次插入的時候都是直接插到葉子節點的,所以每次遞歸回去的時候就要進行旋轉操作,以讓Treap滿足堆的性質。旋轉操作是不會改變Treap的中序遍歷的結果的,也就是說不會破壞二叉搜索樹的性質,而且可以讓Treap滿足堆的性質。

#include<cstdio>
#include<cstring>
#include<ctime>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+10;
struct Treap
{
    struct zp
    {
        int son[2];
        int fix,id,p;
    } tree[maxn];
    int root,sz;
    void init()
    {
        root=0;
        sz=0;
    }
    int newnode(int id,int p)
    {
        sz++;
        tree[sz].fix=rand();//隨機優先級
        tree[sz].id=id,tree[sz].p=p;
        tree[sz].son[0]=tree[sz].son[1]=0;
        return sz;
    }
    void rotate(int &o,int d)//旋轉操作 0代表左旋 1代表右旋
    {
        int k=tree[o].son[d^1];
        tree[o].son[d^1]=tree[k].son[d];
        tree[k].son[d]=o;
        o=k;
    }
    void remove(int &u,int p)//刪除操作 刪除題目上優先級爲p的節點
    {
        if(tree[u].p==p)
        {
            if(tree[u].son[0]!=0&&tree[u].son[1]!=0)//當這個點的兩個兒子都不爲空時爲了刪除它就要將它往下旋轉,直到它的某個兒子爲空爲止
            {
                int d=tree[tree[u].son[0]].fix<tree[tree[u].son[1]].fix?0:1;//判斷是左旋還是右旋
                rotate(u,d);
                remove(tree[u].son[d],p);//遞歸刪除
            }
            else//某個兒子節點爲空後刪除節點,將不爲空的節點接到它的父節點上
            {
                    if(tree[u].son[0]==0) u=tree[u].son[1];
                    else u=tree[u].son[0];
            }
        }
        else remove(tree[u].son[p>tree[u].p],p);
    }
    void insert(int &i,int id,int p)//插入
    {
        if(i==0) i=newnode(id,p);
        else
        {
            int d=p<tree[i].p?0:1;//判斷找那個兒子
            insert(tree[i].son[d],id,p);
            if(tree[i].fix<tree[tree[i].son[d]].fix) rotate(i,d^1);//遞歸回來後進行旋轉
        }
    }
    void query(int &i,int d)//查詢最大值 最小值
    {
        if(i==0)
        {
            printf("0\n");
            return ;
        }
        if(tree[i].son[d]==0)
        {
            printf("%d\n",tree[i].id);
            remove(root,tree[i].p);
        }
        else query(tree[i].son[d],d);
    }
}ac;
int main()
{
    ac.init();
    int opt;
    while(scanf("%d",&opt)!=EOF && opt)
    {
        if(opt==1)
        {
            int id,p;
            scanf("%d%d",&id,&p);
            ac.insert(ac.root,id,p);
        }
        else ac.query(ac.root,(opt-2)^1);
    }
    return 0;
}
發佈了110 篇原創文章 · 獲贊 18 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章