FHQTreap刷题记录

  • 分裂:如图,按值分裂,u比k大则切黄色的一🔪,此时u接上Y的左子树,然后可见Y的左子树仍然空着,u也递归到其左子树。同理,u比k大则切红色的一🔪,此时u接上X的右子树,然后可见X的右子树仍然空着,u也递归到其右子树。
  • 合并:随机切红色和紫色,合并的是切口上面部分,return合并后的根,,比如,如果切红色,那递归合并X的右子树和Y,并且X的右儿子的指针指向X的右子树和Y合并的结果。

 

BZOJ3224: Tyvj 1728 普通平衡树

  • 模板题,代码:
     1 #include <bits/stdc++.h>
     2 #define nmax 100010
     3  
     4 using namespace std;
     5 int s[nmax][2]={0};
     6 int si[nmax]={0}, v[nmax], r[nmax];
     7 int cnt = 0;
     8  
     9 void up(int p){
    10     si[p] = si[ s[p][0] ] + si[ s[p][1] ] + 1;
    11 }
    12  
    13 void spilit(int& x, int& y, int k, int u){
    14     if(!u) { x=y=0; return; }
    15     if(v[u] <= k){
    16         x = u;
    17         spilit(s[x][1], y, k, s[x][1]);
    18     }else{
    19         y = u;
    20         spilit(x, s[y][0], k, s[y][0]);
    21     }
    22     up(u);
    23 }
    24  
    25 int merge(int x, int y){
    26     if(!x || !y){ return x|y; }
    27     if(r[x] > r[y]) {
    28         s[x][1] = merge(s[x][1], y);
    29         up(x);
    30         return x;
    31     }else{
    32         s[y][0] = merge(x, s[y][0]);
    33         up(y);
    34         return y;
    35     }
    36 }
    37  
    38 int kth(int k, int u){
    39     int ans, t;
    40     while(1){
    41         t = si[ s[u][0] ] + 1;
    42         if(k == t) { ans = u; break; }
    43         else if(k < t) u=s[u][0];
    44         else { u=s[u][1]; k-=t; }
    45     }
    46     return v[ans];
    47 }
    48  
    49 int newnode(int k){
    50     cnt++;
    51     v[cnt] = k;
    52     si[cnt] = 1;
    53     r[cnt] = rand();
    54     return cnt;
    55 }
    56  
    57 int main(){
    58     int n, op, num;
    59     cin >> n;
    60     int x, y, z, root=0;
    61     while(n--){
    62         scanf("%d%d", &op, &num);
    63         switch (op)
    64         {
    65             case 1:
    66                 z = newnode(num);
    67                 spilit(x, y, num, root);
    68                 root = merge( merge(x,z) , y );
    69                 break;
    70             case 2:
    71                 spilit(x, y, num, root);
    72                 spilit(x, z, num-1, x);
    73                 z = merge(s[z][0], s[z][1]);
    74                 root = merge( merge(x,z), y );
    75                 break;
    76             case 3:
    77                 spilit(x, y, num-1, root);
    78                 printf("%d\n", si[x]+1);
    79                 root = merge(x, y);
    80                 break;
    81             case 4:
    82                 printf("%d\n", kth(num, root) );
    83                 break;
    84             case 5:
    85                 spilit(x, y, num-1, root);
    86                 printf("%d\n", kth(si[x], x) );
    87                 root = merge(x, y);
    88                 break;
    89             default:
    90                 spilit(x, y, num, root);
    91                 printf("%d\n", kth(1, y) );
    92                 root = merge(x, y);
    93                 break;
    94         }
    95     }
    96     return 0;
    97 }
    ( ఠൠఠ )ノ

     

posted @ 2019-11-20 00:43  连昵称都不能重复  阅读(183)  评论(0编辑  收藏  举报