数据结构: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 }
相关文章
相关标签/搜索