zoukankan      html  css  js  c++  java
  • HDU3487 play with chain

    题目大意:给出1到n的有序数列,现在有两个操作:

    1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。

    2.FLIP a b  把第a到第b个数反转。

    经过总共m次操作后,求现在的数列。

    n,m<300000

    分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。

    维护size,rev(反转标记)即可。

    通过size可以找到第k大,通过rev做懒标记,可以进行反转。

    具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。

    因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define MAXN 300505
      6 int tot,root,n,m,a,b,c;
      7 char str[10];
      8 struct node
      9 {
     10     int val,fa,sz;
     11     bool rev;
     12     int ch[2];
     13 }tree[MAXN];
     14 void newnode(int &r,int father,int val)
     15 {
     16     tot++;
     17     r=tot;
     18     tree[tot].fa=father;
     19     tree[tot].val=val;
     20 }
     21 void build(int &root,int l,int r,int father)
     22 {
     23     if(l>r)return;
     24     int mid=(l+r)/2;
     25     newnode(root,father,mid);
     26     build(tree[root].ch[0],l,mid-1,root);
     27     build(tree[root].ch[1],mid+1,r,root);
     28     tree[root].sz=tree[tree[root].ch[0]].sz+tree[tree[root].ch[1]].sz+1;
     29     }
     30 void init()
     31 {
     32     tot=root=0;
     33     memset(tree,0,sizeof tree);
     34     newnode(root,0,-1);
     35     newnode(tree[root].ch[1],root,-1);
     36     build(tree[tree[1].ch[1]].ch[0],1,n,tree[1].ch[1]);
     37     tree[tree[1].ch[1]].sz=tree[tree[tree[1].ch[1]].ch[0]].sz+1;
     38     tree[1].sz=tree[tree[1].ch[1]].sz+1;
     39 }
     40 void pd(int &r)
     41 {
     42     if(tree[r].rev==1)
     43     {swap(tree[r].ch[0],tree[r].ch[1]);
     44         tree[tree[r].ch[0]].rev^=1;
     45         tree[tree[r].ch[1]].rev^=1;
     46         tree[r].rev=0;
     47     }
     48     
     49 }
     50 void pu(int &r)
     51 {
     52     tree[r].sz=tree[tree[r].ch[0]].sz+tree[tree[r].ch[1]].sz+1;
     53     }
     54 void rotato(int &r,bool kind)
     55 {
     56     int y=tree[r].fa;
     57     int yy=tree[y].fa;
     58     if(yy)
     59     {
     60         tree[yy].ch[tree[yy].ch[1]==y]=r;
     61         }
     62         tree[r].fa=yy;
     63         tree[tree[r].ch[kind]].fa=y;
     64     tree[y].ch[!kind]=tree[r].ch[kind];
     65         tree[y].fa=r;
     66         tree[r].ch[kind]=y;
     67         pu(y);
     68         pu(r);
     69 }
     70 void splay(int &r,int goal)
     71 {
     72     while(tree[r].fa!=goal)
     73     {
     74         int y=tree[r].fa;
     75         int yy=tree[y].fa;
     76         if(yy==goal)rotato(r,tree[y].ch[0]==r);
     77         else
     78         {
     79             int kind=(tree[y].ch[0]==r);
     80             if(tree[yy].ch[kind]==y)
     81             {
     82                 rotato(r,kind);
     83                 rotato(r,!kind);
     84             }
     85             else
     86             {
     87                 rotato(y,kind);
     88                 rotato(r,kind);
     89             }
     90         }
     91     }
     92     if(goal==0)
     93         root=r;
     94 }
     95 int find(int r,int k)
     96     {
     97     pd(r);
     98     if(tree[tree[r].ch[0]].sz==k-1)
     99         return r;
    100     else if(tree[tree[r].ch[0]].sz>k-1)
    101         return find(tree[r].ch[0],k);
    102         else return find(tree[r].ch[1],k-tree[tree[r].ch[0]].sz-1);
    103     }
    104     void print(int &r)
    105     {
    106     pd(r);
    107     if(tree[r].ch[0])
    108     print(tree[r].ch[0]);    
    109         if(tree[r].val!=-1){printf("%d",tree[r].val);if(tot>3)printf(" ");tot--;}
    110         if(tree[r].ch[1])
    111         print(tree[r].ch[1]);
    112     }
    113 int main()
    114 {
    115     
    116     while(scanf("%d%d",&n,&m)&&(n>=0&&m>=0))
    117     {
    118     init();
    119     for(int i=0;i<m;i++)
    120     {
    121         scanf("%s",str);
    122         if(str[0]=='C')
    123         {
    124             scanf("%d%d%d",&a,&b,&c);
    125             int x1=find(root,a);
    126             int y1=find(root,b+2);
    127             splay(x1,0);
    128             splay(y1,root);
    129             int t=tree[tree[root].ch[1]].ch[0];
    130             tree[tree[root].ch[1]].ch[0]=0;
    131             pu(tree[root].ch[1]);
    132             pu(root);
    133             x1=find(root,c+1);
    134             y1=find(root,c+2);
    135             splay(x1,0);
    136             splay(y1,root);
    137             tree[tree[root].ch[1]].ch[0]=t;
    138             tree[t].fa=tree[root].ch[1];
    139             pu(tree[root].ch[1]);
    140             pu(root);
    141         }
    142         else 
    143         {
    144             scanf("%d%d",&a,&b);
    145             int x=find(root,a);
    146             int y=find(root,b+2);
    147             splay(x,0);
    148             splay(y,root);
    149             tree[tree[tree[root].ch[1]].ch[0]].rev^=1;
    150         }
    151     }
    152     print(root);
    153     printf("
    ");
    154     }
    155 }
    View Code
  • 相关阅读:
    Node
    HTTP权威指南
    一些乱七八糟的思考积累
    有限状态机
    奇怪问题引用到其它文件夹项目文件方法
    dijkstra+堆优化
    高精度
    BUAA 1301 最短路
    阿里云服务器ECS(Centos8)下安装和配置python3.8
    Cheat Sheet
  • 原文地址:https://www.cnblogs.com/hefenghhhh/p/4650519.html
Copyright © 2011-2022 走看看