zoukankan      html  css  js  c++  java
  • HDU 3487 Play with Chain(Splay)

    题目大意

    给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作

      操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数列中第 c 个数的后面

      操作2. FLIP a b 表示把数列中第 a 个数到第 b 个数翻转

    经过 m 个操作之后,输出这个数列

    1≤n, m≤3*100000

    做法分析

    这题也不好用线段树做,用 Splay 很快就搞出来了

    对于"操作1. CUT a b c" ,只需要将 a-1 旋转到根,b+1旋转成 a-1 的子树,那么 [a, b] 之间的树变成了 b+1 的左子树,将整个子树从原树中删去,并把 b+1 旋转到根。之后把 c 旋转到根,c+1 旋转成 c 的子树,再把刚才删掉的子树添加到 c+1 的左子树上(没添加之前,c+1 的左子树必然为空)

    对于“操作2. FLIP a b”,只需要给树中每个节点一个 rev 标记表示是否需要翻转以该节点为根的子树中序遍历所得的数列,和线段树差不多的使用懒操作就行了

    还是那些细节问题,在什么时候 pushDown,什么时候 pushUp,写代码的时候一定要想清楚

    参考代码

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 
      6 using namespace std;
      7 
      8 const int N=300005, INF=0x7fffffff;
      9 
     10 struct Splay_Tree {
     11     struct Node {
     12         int val, Size, son[2];
     13         bool rev;
     14         inline void init(int _val) {
     15             val=_val, Size=1;
     16             son[0]=son[1]=rev=0;
     17         }
     18     } T[N];
     19     int fa[N], root;
     20     queue <int> ans;
     21 
     22     inline void pushUp(int x) {
     23         T[x].Size=1;
     24         if(T[x].son[0]) T[x].Size+=T[T[x].son[0]].Size;
     25         if(T[x].son[1]) T[x].Size+=T[T[x].son[1]].Size;
     26     }
     27 
     28     inline void pushDown(int x) {
     29         if(!T[x].rev) return;
     30         if(T[x].son[0]) T[T[x].son[0]].rev^=1;
     31         if(T[x].son[1]) T[T[x].son[1]].rev^=1;
     32         swap(T[x].son[0], T[x].son[1]);
     33         T[x].rev=0;
     34     }
     35 
     36     void Rotate(int x, int kind) {
     37         int y=fa[x], z=fa[y];
     38         pushDown(y), pushDown(x);
     39         T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y;
     40         T[x].son[kind]=y, fa[y]=x;
     41         T[z].son[T[z].son[1]==y]=x, fa[x]=z;
     42         pushUp(y);
     43     }
     44 
     45     void Splay(int x, int goal) {
     46         if(x==goal) return;
     47         while(fa[x]!=goal) {
     48             int y=fa[x], z=fa[y];
     49             int rx=T[y].son[0]==x, ry=T[z].son[0]==y;
     50             if(z==goal) Rotate(x, rx);
     51             else {
     52                 if(rx==ry) Rotate(y, ry);
     53                 else Rotate(x, rx);
     54                 Rotate(x, ry);
     55             }
     56         }
     57         pushUp(x);
     58         if(goal==0) root=x;
     59     }
     60 
     61     int Select(int pos, int goal) {
     62         int u=root;
     63         pushDown(u);
     64         while(T[T[u].son[0]].Size!=pos) {
     65             if(T[T[u].son[0]].Size>pos) u=T[u].son[0];
     66             else {
     67                 pos-=T[T[u].son[0]].Size+1;
     68                 u=T[u].son[1];
     69             }
     70             pushDown(u);
     71         }
     72         Splay(u, goal);
     73         return u;
     74     }
     75 
     76     void Cut(int L, int R, int pos) {
     77         int u=Select(L-1, 0), v=Select(R+1, u);
     78         int x=T[v].son[0];
     79         fa[x]=0, T[v].son[0]=0;
     80         Splay(v, 0);
     81         u=Select(pos, 0), v=Select(pos+1, u);
     82         T[v].son[0]=x, fa[x]=v;
     83         Splay(x, 0);
     84     }
     85 
     86     void Reverse(int L, int R) {
     87         int u=Select(L-1, 0), v=Select(R+1, u);
     88         T[T[v].son[0]].rev^=1;
     89     }
     90 
     91     void DFS(int u) {
     92         pushDown(u);
     93         if(T[u].son[0]) DFS(T[u].son[0]);
     94         ans.push(T[u].val);
     95         if(T[u].son[1]) DFS(T[u].son[1]);
     96     }
     97 
     98     void Display(int n) {
     99         while(!ans.empty()) ans.pop();
    100         DFS(root);
    101         for(int cnt=0, x; cnt<n; cnt++, ans.pop()) {
    102             for(x=ans.front(); x==-INF; ans.pop(), x=ans.front());
    103             printf("%d", x);
    104             if(cnt+1==n) printf("
    ");
    105             else printf(" ");
    106         }
    107     }
    108 
    109     int build(int L, int R) {
    110         if(L>R) return 0;
    111         if(L==R) return L;
    112         int mid=(L+R)>>1, sL, sR;
    113         T[mid].son[0]=sL=build(L, mid-1);
    114         T[mid].son[1]=sR=build(mid+1, R);
    115         fa[sL]=fa[sR]=mid;
    116         pushUp(mid);
    117         return mid;
    118     }
    119 
    120     void init(int n) {
    121         T[0].init(-INF), T[1].init(-INF), T[n+2].init(-INF);
    122         for(int i=2; i<=n+1; i++) T[i].init(i-1);
    123         root=build(1, n+2);
    124         T[0].Size=0, T[0].son[1]=root, fa[root]=0, fa[0]=0;
    125     }
    126 } hehe;
    127 int n, m;
    128 char cmd[10];
    129 
    130 int main() {
    131 //    freopen("in", "r", stdin);
    132     while(scanf("%d%d",&n, &m), n!=-1 || m!=-1) {
    133         hehe.init(n);
    134         for(int i=0, a, b, c; i<m; i++) {
    135             scanf("%s", cmd);
    136             if(cmd[0]=='C') {
    137                 scanf("%d%d%d", &a, &b, &c);
    138                 hehe.Cut(a, b, c);
    139             }
    140             else {
    141                 scanf("%d%d", &a, &b);
    142                 hehe.Reverse(a, b);
    143             }
    144         }
    145         hehe.Display(n);
    146     }
    147     return 0;
    148 }
    HDU 3487

    题目链接 & AC 通道

    HDU 3487 Play with Chain

  • 相关阅读:
    Excel导入导出DataGridView
    博客开通第一天
    windows10 VM12 安装Mac OS X 10.11
    js判断IE浏览器及版本
    C# MD5 加密
    WindowsErrorCode
    localStorage,sessionStorage的使用
    js实现页面锚点定位动画滚动
    纯js实现页面返回顶部的动画
    HTML table固定表头
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3271347.html
Copyright © 2011-2022 走看看