數據結構:Treap

關於重量平衡樹的相關概念能夠參考姊妹文章:重量平衡樹之替罪羊樹ios

Treap是依靠旋轉來維護平衡的重量平衡樹中最爲好寫的一中,由於它的旋轉不是LL就是RR函數

對於每個新的節點,它給這個節點分配了一個隨機數,用做優先級,而後以這個優先級來維護一個堆結構spa

因爲堆自己就是徹底二叉樹結構,這樣維護以後的樹就無限接近於徹底二叉樹,因此仍是很神奇的code

這棵樹知足BST的一切性質,除了不能處理序列問題以外已經無敵了blog

應該說,拋去動態樹問題以外,這是實戰最好用的樹了ci

咱們仍是先看定義:it

struct Tree { int v,w; int size; int rnd; int ch[2]; }t[maxn]; int root; int size; int ans=0;

在這裏v是值,w是同值的節點個數,size是子樹的節點總數,rnd是優先級,外面:root是根節點,size是根節點中元素個數,ans是統計答案用的臨時變量io

咱們這裏仍是先介紹插入操做,平衡樹問題若是不是處理序列的,建議就一個一個插模板

void insert(int &k,int x) { if(k==0) { size++; k=size; t[k].size=t[k].w=1; t[k].v=x; t[k].rnd=rand(); return; } t[k].size++; if(t[k].v==x) t[k].w++; else if(x>t[k].v) { insert(t[k].ch[1],x); if(t[t[k].ch[1]].rnd<t[k].rnd) lturn(k); } else { insert(t[k].ch[0],x); if(t[t[k].ch[0]].rnd<t[k].rnd) rturn(k); } }

插入時根據是不是葉子節點,遍歷到的節點的w值等進行維護class

每次插入要判斷一下是否知足堆結構,進行相應的旋轉調整

下面給出旋轉調整的函數,基本上能夠做爲左旋和右旋的模板了

void rturn(int &k) { int tmp=t[k].ch[0]; t[k].ch[0]=t[tmp].ch[1]; t[tmp].ch[1]=k; t[tmp].size=t[k].size; update(k); k=tmp; } void lturn(int &k) { int tmp=t[k].ch[1]; t[k].ch[1]=t[tmp].ch[0]; t[tmp].ch[0]=k; t[tmp].size=t[k].size; update(k); k=tmp; }

而後咱們給出update函數,這裏要維護的東西不多,只有一個size,因此這個時候的update就是更新size用的

void update(int k) { t[k].size=t[t[k].ch[0]].size+t[t[k].ch[1]].size+t[k].w; }

而後是四種基本查詢工做,各類平衡樹基本一致,也能夠做爲模板記下來了

int query_rank(int k,int x) { if(k==0) return 0; if(t[k].v==x) return t[t[k].ch[0]].size+1; else if(x>t[k].v) return t[t[k].ch[0]].size+t[k].w+query_rank(t[k].ch[1],x); else 
        return query_rank(t[k].ch[0],x); } int query_num(int k,int x) { if(k==0) return 0; if(x<=t[t[k].ch[0]].size) return query_num(t[k].ch[0],x); else if(x>t[t[k].ch[0]].size+t[k].w) return query_num(t[k].ch[1],x-t[t[k].ch[0]].size-t[k].w); else
        return t[k].v; } void query_pro(int k,int x) { if(k==0) return; if(t[k].v<x) ans=k,query_pro(t[k].ch[1],x); else query_pro(t[k].ch[0],x); } void query_sub(int k,int x) { if(k==0) return; if(t[k].v>x) ans=k,query_sub(t[k].ch[0],x); else query_sub(t[k].ch[1],x); }

最後咱們給出完整的模板,這棵樹必定要熟練掌握,只要是平衡樹問題,很大可能都是用它來完成的

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;  5 const int maxn=100005;  6 int n;  7 struct Tree  8 {  9     int v,w;  10     int size;  11     int rnd;  12     int ch[2];  13 }t[maxn];  14 int root;  15 int size;  16 int ans=0;  17 void update(int k)  18 {  19     t[k].size=t[t[k].ch[0]].size+t[t[k].ch[1]].size+t[k].w;  20 }  21 void rturn(int &k)  22 {  23     int tmp=t[k].ch[0];  24     t[k].ch[0]=t[tmp].ch[1];  25     t[tmp].ch[1]=k;  26     t[tmp].size=t[k].size;  27  update(k);  28     k=tmp;  29 }  30 void lturn(int &k)  31 {  32     int tmp=t[k].ch[1];  33     t[k].ch[1]=t[tmp].ch[0];  34     t[tmp].ch[0]=k;  35     t[tmp].size=t[k].size;  36  update(k);  37     k=tmp;  38 }  39 void insert(int &k,int x)  40 {  41     if(k==0)  42  {  43         size++;  44         k=size;  45         t[k].size=t[k].w=1;  46         t[k].v=x;  47         t[k].rnd=rand();  48         return;  49  }  50     t[k].size++;  51     if(t[k].v==x)  52         t[k].w++;  53     else if(x>t[k].v)  54  {  55         insert(t[k].ch[1],x);  56         if(t[t[k].ch[1]].rnd<t[k].rnd)  57  lturn(k);  58  }  59     else
 60  {  61         insert(t[k].ch[0],x);  62         if(t[t[k].ch[0]].rnd<t[k].rnd)  63  rturn(k);  64  }  65 }  66 void del(int &k,int x)  67 {  68     if(k==0)  69         return;  70     if(t[k].v==x)  71  {  72         if(t[k].w>1)  73  {  74             t[k].w--;  75             t[k].size--;  76             return;  77  }  78         if(t[k].ch[0]*t[k].ch[1]==0)  79             k=t[k].ch[0]+t[k].ch[1];  80         else if(t[t[k].ch[0]].rnd<t[t[k].ch[1]].rnd)  81  rturn(k),del(k,x);  82         else
 83  lturn(k),del(k,x);  84  }  85     else if(x>t[k].v)  86         t[k].size--,del(t[k].ch[1],x);  87     else
 88         t[k].size--,del(t[k].ch[0],x);  89 }  90 int query_rank(int k,int x)  91 {  92     if(k==0)  93         return 0;  94     if(t[k].v==x)  95         return t[t[k].ch[0]].size+1;  96     else if(x>t[k].v)  97         return t[t[k].ch[0]].size+t[k].w+query_rank(t[k].ch[1],x);  98     else 
 99         return query_rank(t[k].ch[0],x); 100 } 101 int query_num(int k,int x) 102 { 103     if(k==0) 104         return 0; 105     if(x<=t[t[k].ch[0]].size) 106         return query_num(t[k].ch[0],x); 107     else if(x>t[t[k].ch[0]].size+t[k].w) 108         return query_num(t[k].ch[1],x-t[t[k].ch[0]].size-t[k].w); 109     else
110         return t[k].v; 111 } 112 void query_pro(int k,int x) 113 { 114     if(k==0) 115         return; 116     if(t[k].v<x) 117         ans=k,query_pro(t[k].ch[1],x); 118     else
119         query_pro(t[k].ch[0],x); 120 } 121 void query_sub(int k,int x) 122 { 123     if(k==0) 124         return; 125     if(t[k].v>x) 126         ans=k,query_sub(t[k].ch[0],x); 127     else
128         query_sub(t[k].ch[1],x); 129 } 130 int main() 131 { 132     cin>>n; 133     int tmp,x; 134     for(int i=1;i<=n;i++) 135  { 136         cin>>tmp>>x; 137         switch(tmp) 138  { 139             case 1:insert(root,x);break; 140             case 2:del(root,x);break; 141             case 3:cout<<query_rank(root,x)<<endl;break; 142             case 4:cout<<query_num(root,x)<<endl;break; 143             case 5:ans=0;query_pro(root,x);cout<<t[ans].v<<endl;break; 144             case 6:ans=0;query_sub(root,x);cout<<t[ans].v<<endl;break; 145  } 146  } 147     return 0; 148 }
相關文章
相關標籤/搜索