zoukankan      html  css  js  c++  java
  • 平衡树

    P3369 【模板】普通平衡树

    https://www.luogu.org/problemnew/show/P3369

    BST

     1 struct BST {
     2     int l, r; // 左右子节点在数组中的下标
     3     int val;  // 节点关键码
     4 } a[SIZE]; // 数组模拟链表
     5 int tot, root, INF = 1<<30;
     6 
     7 int New(int val) {
     8     a[++tot].val = val;
     9     return tot;
    10 }
    11 
    12 void Build() {
    13     New(-INF), New(INF);
    14     root = 1, a[1].r = 2;
    15 }
    16 
    17 int Get(int p, int val) {
    18     if (p == 0) return 0; // 检索失败
    19     if (val == a[p].val) return p; // 检索成功
    20     return val < a[p].val ? Get(a[p].l, val) : Get(a[p].r, val);
    21 }
    22 
    23 void Insert(int &p, int val) {
    24     if (p == 0) {
    25         p = New(val); // 注意p是引用,其父节点的l或r值会被同时更新
    26         return;
    27     }
    28     if (val == a[p].val) return;
    29     if (val < a[p].val) Insert(a[p].l, val);
    30     else Insert(a[p].r, val);
    31 }
    32 
    33 int GetNext(int val) {
    34     int ans = 2; // a[2].val==INF
    35     int p = root;
    36     while (p) {
    37         if (val == a[p].val) { // 检索成功
    38             if (a[p].r > 0) { // 有右子树
    39                 p = a[p].r;
    40                 // 右子树上一直向左走
    41                 while (a[p].l > 0) p = a[p].l;
    42                 ans = p;
    43             }
    44             break;
    45         }
    46         // 每经过一个节点,都尝试更新后继
    47         if (a[p].val > val && a[p].val < a[ans].val) ans = p;
    48         p = val < a[p].val ? a[p].l : a[p].r;
    49     }
    50     return ans;
    51 }
    52 
    53 void Remove(int val) {
    54     // 检索val,得到节点p
    55     int &p = root;
    56     while (p) {
    57         if (val == a[p].val) break;
    58         p = val < a[p].val ? a[p].l : a[p].r;
    59     }
    60     if (p == 0) return;
    61     if (a[p].l == 0) { // 没有左子树
    62         p = a[p].r; // 右子树代替p的位置,注意p是引用
    63     }
    64     else if (a[p].r == 0) { // 没有右子树
    65         p = a[p].l; // 左子树代替p的位置,注意p是引用
    66     }
    67     else { // 既有左子树又有右子树
    68         // 求后继节点
    69         int next = a[p].r;
    70         while (a[next].l > 0) next = a[next].l;
    71         // next一定没有左子树,直接删除
    72         Remove(a[next].val);
    73         // 令节点next代替节点p的位置
    74         a[next].l = a[p].l, a[next].r = a[p].r;
    75         p = next; // 注意p是引用
    76     }
    77 }

    treap

    利用随机权值维护堆的形态

      1 const int N=100010,INF=1<<30;
      2 struct treap{int l,r,c,dat,cnt,size;}a[N];
      3 int m,tot,root;
      4 
      5 int newnode(int val)
      6 {
      7     a[++tot].c=val;
      8     a[tot].dat=rand();
      9     a[tot].size=a[tot].cnt=1;
     10     return tot;
     11 }
     12 
     13 void update(int x)
     14 {
     15     a[x].size=a[a[x].l].size+a[a[x].r].size+a[x].cnt;
     16 }
     17 
     18 void build()
     19 {
     20     newnode(-INF),newnode(INF);
     21     root=1,a[1].r=2;
     22     update(root);
     23 }
     24 
     25 void zlg(int &p)//zag
     26 {
     27     int q=a[p].r;
     28     a[p].r=a[q].l,a[q].l=p,p=q;
     29     update(a[p].l),update(p);
     30 }
     31 void zrg(int &p)//zig
     32 {
     33     int q=a[p].l;
     34     a[p].l=a[q].r,a[q].r=p,p=q;
     35     update(a[p].r),update(p);
     36 }
     37 
     38 void insert(int &p,int val)
     39 {
     40     if(p==0) {p=newnode(val);return;}
     41     if(a[p].c==val) {++a[p].cnt,++a[p].size;return;}
     42     if(val<a[p].c) 
     43     {
     44         insert(a[p].l,val);
     45         if(a[p].dat<a[a[p].l].dat) zrg(p);
     46     }
     47     else
     48     {
     49         insert(a[p].r,val);
     50         if(a[p].dat<a[a[p].r].dat) zlg(p);
     51     }
     52     update(p);
     53 }
     54 
     55 int grbv(int p,int val)
     56 {
     57     if(p==0) return 0;
     58     if(a[p].c==val) return a[a[p].l].size+1;
     59     if(a[p].c>val) return grbv(a[p].l,val);
     60     return grbv(a[p].r,val)+a[a[p].l].size+a[p].cnt;
     61 }
     62 
     63 int gvbr(int p,int ran)
     64 {
     65     if(p==0) return INF;
     66     if(a[a[p].l].size>=ran) return gvbr(a[p].l,ran);
     67     else if(a[a[p].l].size+a[p].cnt>=ran) return a[p].c;
     68     else return gvbr(a[p].r,ran-a[a[p].l].size-a[p].cnt);
     69 }
     70 
     71 int getnext(int val)
     72 {
     73     int p=root,ans=2;
     74     while(p)
     75     {
     76         if(a[p].c==val)
     77         {
     78             if(a[p].r>0) 
     79             {
     80                 p=a[p].r;
     81                 while(a[p].l>0)p=a[p].l;
     82                 ans=p;
     83             }
     84             break;
     85         }
     86         if(a[p].c>val&&a[p].c<a[ans].c) ans=p;
     87         if(val<a[p].c) p=a[p].l;
     88         else p=a[p].r;
     89     }
     90     return a[ans].c;
     91 }
     92 
     93 int getlast(int val)
     94 {
     95     int p=root,ans=1;
     96     while(p)
     97     {
     98         if(a[p].c==val)//||(a[p].c>val&&a[p].l==0)
     99         {
    100             if(a[p].l>0)
    101             {
    102                 p=a[p].l;
    103                 while(a[p].r>0) p=a[p].r;
    104                 ans=p;
    105             } 
    106             break;
    107         }
    108         if(a[p].c<val&&a[p].c>a[ans].c) ans=p;
    109         if(val<a[p].c) p=a[p].l;
    110         else p=a[p].r;
    111     }
    112     return a[ans].c;
    113 }
    114 
    115 void remove(int &p,int val)
    116 {
    117     if(p==0) return;
    118     if(a[p].c==val)
    119     {
    120         if(a[p].cnt>1)
    121         {
    122             a[p].cnt--,update(p);
    123             return;
    124         }
    125         if(a[p].l||a[p].r)
    126         {
    127             if(a[p].r==0 || a[a[p].l].dat>a[a[p].r].dat)
    128                 zrg(p),remove(a[p].r,val);
    129             else zlg(p),remove(a[p].l,val);
    130             update(p);
    131         }
    132         else p=0;
    133         return;
    134     }
    135     if(val<a[p].c) remove(a[p].l,val);
    136     else remove(a[p].r,val);
    137     update(p);
    138 }
    139 
    140 int main()
    141 {
    142     srand(time(NULL));
    143     cin>>m;build();
    144     FOR(i,1,m)
    145     {
    146         int opt,x;cin>>opt>>x;
    147         switch(opt)
    148         {
    149             case 1:insert(root,x);break;
    150             case 3:cout<<grbv(root,x)-1<<endl;break;
    151             case 4:cout<<gvbr(root,x+1)<<endl;break;
    152             case 5:cout<<getlast(x)<<endl;break;
    153             case 6:cout<<getnext(x)<<endl;break;
    154             case 2:remove(root,x);break;
    155         }
    156     }
    157     return 0;
    158 }
  • 相关阅读:

    双向链表
    obs分析 笔记
    循环链表
    静态链表
    链式顺序表
    线性表
    ffmpeg-4.1.1-win64-dev在vs2017的搭建
    G1 与 CMS 两个垃圾收集器的对比
    垃圾回收算法有几种类型? 他们对应的优缺点又是什么?
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10658779.html
Copyright © 2011-2022 走看看