zoukankan      html  css  js  c++  java
  • [BZOJ3223]文艺平衡树

    题目大意:
      实现一个数据结构支持区间翻转操作共$n(nleq100000)$次。

    思路:
      Splay维护区间。
      对于区间$[l,r]$的翻转可以先将$l-1$旋转到根,再把$r+1$旋转到根的右子结点,此时根结点的右子结点的左子树就是需要翻转的区间。注意翻转过后结点的权值可能不满足二叉搜索树的性质,也不需要满足二叉搜索树的性质。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int N=100003;
    12 int n,ans[N];
    13 class SplayTree {
    14     private:
    15         int val[N],par[N],size[N],ch[N][2];
    16         bool rev[N];
    17         int sz,new_node(const int &x) {
    18             val[++sz]=x;
    19             size[sz]=1;
    20             return sz;
    21         }
    22         void push_down(const int &p) {
    23             if(!rev[p]) return;
    24             std::swap(ch[p][0],ch[p][1]);
    25             rev[ch[p][0]]^=1;
    26             rev[ch[p][1]]^=1;
    27             rev[p]=0;
    28         }
    29         void push_up(const int &p) {
    30             size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
    31         }
    32         void rotate(const int &x) {
    33             const int y=par[x],z=par[y];
    34             push_down(y),push_down(x);
    35             const bool b=x==ch[y][0];
    36             par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x;
    37             if(par[x]=z) par[ch[z][ch[z][1]==y]=x]=z;
    38             push_up(y),push_up(x);
    39         }
    40         void splay(int x,const int &goal) {
    41             for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) {
    42                 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y);
    43             }
    44             if(!goal) root=x;
    45         }
    46     public:
    47         int root;
    48         void insert(const int &x) {
    49             int y=root;
    50             while(ch[y][x>val[y]]) y=ch[y][x>val[y]];
    51             par[ch[y][x>val[y]]=new_node(x)]=y;
    52             splay(sz,0);
    53         }
    54         void build(const int &n) {
    55             for(register int i=0;i<=n+1;i++) insert(i);
    56         }
    57         int find(int x) {
    58             for(register int y=root;;y=ch[y][size[ch[y][0]]<x]) {
    59                 push_down(y);
    60                 if(par[y]&&y==ch[par[y]][1]) x-=size[ch[par[y]][0]]+1;
    61                 if(size[ch[y][0]]==x) return y;
    62             }
    63         }
    64         void reverse(const int &l,const int &r) {
    65             splay(find(l-1),0);
    66             splay(find(r+1),root);
    67             rev[ch[ch[root][1]][0]]^=1;
    68         }
    69         void dfs(const int &p) {
    70             push_down(p);
    71             if(ch[p][0]) dfs(ch[p][0]);
    72             if(val[p]&&val[p]<=n) ans[++ans[0]]=val[p];
    73             if(ch[p][1]) dfs(ch[p][1]);
    74         }
    75 };
    76 SplayTree t;
    77 int main() {
    78     t.build(n=getint());
    79     for(register int i=getint();i;i--) {
    80         const int l=getint(),r=getint();
    81         t.reverse(l,r);
    82     }
    83     t.dfs(t.root);
    84     for(register int i=1;i<=n;i++) printf("%d ",ans[i]);
    85     return 0;
    86 }
  • 相关阅读:
    DP——背包问题(三)
    堆——练习题
    DP——背包问题(二)
    二叉树的后序遍历(暴力版) 小白菜oj 1034
    树状数组2模板 Luogu 3368
    树状数组1模板 Luogu 3374
    DP——最长上升子序列(n^2与n log n)
    线段树(区间修改)模板题 Luogu 2357 守墓人
    c语言学习摘录
    python 学习摘录
  • 原文地址:https://www.cnblogs.com/skylee03/p/8510660.html
Copyright © 2011-2022 走看看