• [BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)


    Description 

      您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

    Input

      第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
      接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n

    Output 

      输出一行n个数字,表示原始序列经过m次变换后的结果 

    Sample Input

    5 3
    1 3
    1 3
    1 4

    Sample Output

    4 3 2 1 5

    HINT

      N,M<=100000

    Source

      平衡树

    Solution

      splay的区间翻转。我的习惯是给序列两端加上虚拟节点,这样查询[l, r]时把l旋到根,把r+2旋到根的右儿子。

      我建树时就建成一条链,因为之后的操作可以把它的深度逐渐变成均摊O(logn),所以开始的树的形态不影响复杂度。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct spaly
     4 {
     5     int siz, fa, c[2], rev;
     6 }a[100005];
     7 int root, n;
     8  
     9 void push_up(int k)
    10 {
    11     a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1;
    12 }
    13  
    14 void push_down(int k)
    15 {
    16     if(a[k].rev)
    17     {
    18         swap(a[k].c[0], a[k].c[1]), a[k].rev = 0;
    19         a[a[k].c[0]].rev ^= 1, a[a[k].c[1]].rev ^= 1;
    20     }
    21 }
    22  
    23 void rotate(int &k, int x)
    24 {
    25     int y = a[x].fa, z = a[y].fa;
    26     int dy = a[y].c[1] == x, dz = a[z].c[1] == y;
    27     push_down(y);
    28     if(k == y) k = x, a[x].fa = z;
    29     else a[z].c[dz] = x, a[x].fa = z;
    30     a[y].c[dy] = a[x].c[dy ^ 1], a[a[x].c[dy ^ 1]].fa = y;
    31     a[x].c[dy ^ 1] = y, a[y].fa = x;
    32     push_up(y);
    33 }
    34  
    35 void splay(int &k, int x)
    36 {
    37     push_down(x);
    38     while(k != x)
    39     {
    40         int y = a[x].fa, z = a[y].fa;
    41         if(k != y)
    42             if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x);
    43             else rotate(k, y);
    44         rotate(k, x);
    45     }
    46     push_up(x);
    47 }
    48  
    49 int find(int k, int x)
    50 {
    51     if(!k) return 0;
    52     push_down(k);
    53     if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x);
    54     if(x == a[a[k].c[0]].siz + 1) return k;
    55     return find(a[k].c[1], x - a[a[k].c[0]].siz - 1);
    56 }
    57  
    58 void printf(int k)
    59 {
    60     if(!k) return;
    61     push_down(k), printf(a[k].c[0]);
    62     if(k > 1 && k < n + 2) printf("%d ", k - 1);
    63     printf(a[k].c[1]);
    64 }
    65  
    66 int main()
    67 {
    68     int m, l, r;
    69     scanf("%d%d", &n, &m);
    70     for(int i = 1; i <= n + 2; i++)
    71     {
    72         a[i].siz = n + 3 - i;
    73         a[i].fa = i - 1, a[i].c[1] = i + 1;
    74     }
    75     a[n + 2].c[1] = 0, root = 1;
    76     while(m--)
    77     {
    78         scanf("%d%d", &l, &r);
    79         splay(root, find(root, l));
    80         splay(a[root].c[1], find(root, r + 2));
    81         a[a[a[root].c[1]].c[0]].rev ^= 1;
    82     }
    83     printf(root);
    84     puts("");
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    打开服务器的文档
    笔记
    centos6.5 编译openssl-1.1.1k
    搭建自己的低代码平台
    防火墙ACL配置自动化
    防火墙ACL配置自动化
    【树莓派】读取新大陆(newland)USB条码扫描器数据
    解决eclipse或sts闪退的办法(转)
    浅谈数据库迁移类项目功能测试的基本思路
    ATM取款机优化需求的用例设计
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5357702.html
Copyright © 2020-2023  润新知