zoukankan      html  css  js  c++  java
  • 维修数列 Splay(这可能是我写过最麻烦的题之一了。。。用平衡树维护dp。。。丧心病狂啊。。。。)

    题目来源BZOJ1500

    这题的思路:

    1、这题的话,稍微会splay的人,一般前面四个都不是问题。。主要是最后的一个,要你在修改的同时要维护好最大字段和。。。

    2、最大字段和其实就是区间合并。具体操作可以看POJ2750,这是这道题的简化版本。

    3、然后这题就是三个区间合并嘛。。。慢慢讨论就好了。。。这题写了我一天的时间。。从吃完午饭一直写到了晚上8点才AC。。。

    直接贴代码吧。。这题是我为了学LCT,所以想做做Splay的题先熟悉一下Splay。。。结果选了这个BOSS题。。。心理阴影。。。。

    我觉得我pushup那段写的挺清楚的23333   思路可以看我的pushup和pushdown函数的代码,应该挺好懂的

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<stack>
      5  
      6 using namespace std;
      7  
      8 const int N=500005,INF=0x3f3f3f3f;
      9  
     10 struct Splay_Tree
     11 {
     12     struct Node
     13     {
     14         int val,sum,cover,Size,son[2],mxl,mxr,mx;
     15         bool rev,cov;
     16         void init(int _val)
     17         {
     18             val=sum=mxl=mxr=mx=_val;
     19             Size=1;
     20             rev=cov=cover=son[0]=son[1]=0;
     21         }
     22     } T[N];
     23     stack<int>mem;
     24     int fa[N],root,tot;
     25  
     26     void pushDown(int x)///下放标记(序列操作)
     27     {
     28         if(x==0)return ;
     29         if(T[x].cov)
     30         {
     31             if(T[x].son[0])
     32             {
     33                 T[T[x].son[0]].cov=1;
     34                 T[T[x].son[0]].cover=T[T[x].son[0]].val=T[x].cover;
     35                 T[T[x].son[0]].sum=T[x].cover*T[T[x].son[0]].Size;
     36                 T[T[x].son[0]].rev=0;
     37                 if(T[x].cover>=0)
     38                     T[T[x].son[0]].mx=T[T[x].son[0]].mxl=T[T[x].son[0]].mxr=T[x].cover*T[T[x].son[0]].Size;
     39                 else
     40                     T[T[x].son[0]].mx=T[T[x].son[0]].mxl=T[T[x].son[0]].mxr=T[x].cover;
     41             }
     42             if(T[x].son[1])
     43             {
     44                 T[T[x].son[1]].cov=1;
     45                 T[T[x].son[1]].cover=T[T[x].son[1]].val=T[x].cover;
     46                 T[T[x].son[1]].sum=T[x].cover*T[T[x].son[1]].Size;
     47                 T[T[x].son[1]].rev=0;
     48                 if(T[x].cover>=0)
     49                     T[T[x].son[1]].mx=T[T[x].son[1]].mxl=T[T[x].son[1]].mxr=T[x].cover*T[T[x].son[1]].Size;
     50                 else
     51                     T[T[x].son[1]].mx=T[T[x].son[1]].mxl=T[T[x].son[1]].mxr=T[x].cover;
     52             }
     53             T[x].cov=T[x].cover=T[x].rev=0;
     54         }
     55         if(T[x].rev)
     56         {
     57             if(T[x].son[0])
     58             {
     59                 T[T[x].son[0]].rev^=1;
     60                 swap(T[T[x].son[0]].mxl,T[T[x].son[0]].mxr);
     61             }
     62             if(T[x].son[1])
     63             {
     64                 T[T[x].son[1]].rev^=1;
     65                 swap(T[T[x].son[1]].mxl,T[T[x].son[1]].mxr);
     66             }
     67             swap(T[x].son[0],T[x].son[1]);
     68             T[x].rev=0;
     69         }
     70     }
     71  
     72     void pushUp(int x)///更新节点(序列操作)
     73     {
     74         T[x].Size=1;
     75         T[x].sum=T[x].val;
     76         if(T[x].son[0])
     77             T[x].sum+=T[T[x].son[0]].sum,T[x].Size+=T[T[x].son[0]].Size;
     78         if(T[x].son[1])
     79             T[x].sum+=T[T[x].son[1]].sum,T[x].Size+=T[T[x].son[1]].Size;
     80  
     81         if(T[x].son[0]&&T[x].son[1])
     82         {
     83             T[x].mx=T[x].val;
     84             T[x].mx=max(T[x].mx,T[T[x].son[0]].mx);
     85             T[x].mx=max(T[x].mx,T[T[x].son[1]].mx);
     86             T[x].mx=max(T[x].mx,T[T[x].son[0]].mxr+T[x].val+T[T[x].son[1]].mxl);
     87             T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[0]].mxr);
     88             T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[1]].mxl);
     89  
     90             T[x].mxl=T[T[x].son[0]].mxl;
     91             T[x].mxl=max(T[x].mxl,T[T[x].son[0]].sum+T[x].val);
     92             T[x].mxl=max(T[x].mxl,T[T[x].son[0]].sum+T[x].val+T[T[x].son[1]].mxl);
     93  
     94             T[x].mxr=T[T[x].son[1]].mxr;
     95             T[x].mxr=max(T[x].mxr,T[T[x].son[1]].sum+T[x].val);
     96             T[x].mxr=max(T[x].mxr,T[T[x].son[1]].sum+T[x].val+T[T[x].son[0]].mxr);
     97         }
     98         else if(T[x].son[0]&&!T[x].son[1])
     99         {
    100             T[x].mx=max(T[T[x].son[0]].mxr+T[x].val,T[T[x].son[0]].mx);
    101  
    102             T[x].mx=max(T[x].mx,T[x].val);
    103  
    104             T[x].mxl=max(T[T[x].son[0]].mxl,T[T[x].son[0]].sum+T[x].val);
    105  
    106             T[x].mxr=max(T[x].val,T[x].val+T[T[x].son[0]].mxr);
    107         }
    108         else if(!T[x].son[0]&&T[x].son[1])
    109         {
    110             T[x].mx=max(T[T[x].son[1]].mxl+T[x].val,T[T[x].son[1]].mx);
    111  
    112             T[x].mx=max(T[x].mx,T[x].val);
    113  
    114             T[x].mxl=max(T[x].val,T[x].val+T[T[x].son[1]].mxl);
    115  
    116             T[x].mxr=max(T[T[x].son[1]].mxr,T[T[x].son[1]].sum+T[x].val);
    117         }
    118         else T[x].mxl=T[x].mxr=T[x].mx=T[x].val;
    119  
    120     }
    121  
    122     /*inline void up(int x)///更新节点(普通平衡树操作)
    123     {
    124         T[x].Size=1;
    125         if(T[x].son[0])
    126             T[x].Size+=T[T[x].son[0]].Size;
    127         if(T[x].son[1])
    128             T[x].Size+=T[T[x].son[1]].Size;
    129     }*/
    130  
    131     void Rotate(int x,int kind)///旋转,有左旋右旋(反正配合splay用就好了233)
    132     {
    133         int y=fa[x],z=fa[y];
    134         T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;
    135         T[x].son[kind]=y,fa[y]=x;
    136         T[z].son[T[z].son[1]==y]=x,fa[x]=z;
    137         pushUp(y);
    138     }
    139  
    140     void Splay(int x,int goal)///把下标为x的元素旋转到目标的儿子节点
    141     {
    142         if(x==goal)return ;
    143         while(fa[x]!=goal)
    144         {
    145             int y=fa[x],z=fa[y];
    146             pushDown(z),pushDown(y),pushDown(x);
    147             int rx=T[y].son[0]==x,ry=T[z].son[0]==y;
    148             if(z==goal)Rotate(x,rx);
    149             else
    150             {
    151                 if(rx==ry)Rotate(y,ry);
    152                 else Rotate(x,rx);
    153                 Rotate(x,ry);
    154             }
    155         }
    156         pushUp(x);
    157         if(goal==0)root=x;
    158     }
    159  
    160     int Select(int pos)///查找第k小元素
    161     {
    162         pos--;
    163         int u=root;
    164         pushDown(u);
    165         while(T[T[u].son[0]].Size!=pos)
    166         {
    167             if(pos<T[T[u].son[0]].Size)u=T[u].son[0];
    168             else
    169             {
    170                 pos-=T[T[u].son[0]].Size+1;
    171                 u=T[u].son[1];
    172             }
    173             pushDown(u);
    174         }
    175         return u;
    176     }
    177  
    178  
    179     void Reverse(int L,int R)///序列操作的区间翻转
    180     {
    181         if(L>R)return ;
    182         int u=Select(L-1),v=Select(R+1);
    183         Splay(u,0);
    184         Splay(v,u);
    185         T[T[v].son[0]].rev^=1;
    186         swap(T[T[v].son[0]].mxl,T[T[v].son[0]].mxr);
    187         pushDown(T[v].son[0]);
    188         update(T[v].son[0]);
    189     }
    190  
    191     void Cover(int L,int R,int Val)///序列操作的区间翻转
    192     {
    193         if(L>R)return ;
    194         int u=Select(L-1),v=Select(R+1);
    195         Splay(u,0);
    196         Splay(v,u);
    197         T[T[v].son[0]].cov=1;
    198         T[T[v].son[0]].cover=T[T[v].son[0]].val=Val;
    199         pushDown(T[v].son[0]);
    200         update(T[v].son[0]);
    201     }
    202  
    203     int build(int L,int R,int *a)///区间操作建树
    204     {
    205         if(L>R)return 0;
    206         int mid=(L+R)>>1,sL,sR;
    207         int loc=mem.top();mem.pop();
    208         T[loc].init(a[mid]);
    209         if(L==R)return loc;
    210         T[loc].son[0]=sL=build(L,mid-1,a);
    211         T[loc].son[1]=sR=build(mid+1,R,a);
    212         fa[sL]=fa[sR]=loc;
    213         pushUp(loc);
    214         return loc;
    215     }
    216  
    217     void init(int n,int *a)///区间操作,输入n个元素建树
    218     {
    219         T[0].init(INF);
    220         for(int i=500001;i>=1;i--)
    221             mem.push(i);
    222         root=build(1,n,a),fa[root]=0;
    223         fa[0]=0,T[0].son[1]=root,T[0].Size=0;
    224     }
    225  
    226     void Insert(int pos,int n,int *a)
    227     {
    228         if(n==0)return ;
    229         int u=Select(pos-1),v=Select(pos);
    230         Splay(u,0);
    231         Splay(v,u);
    232         fa[T[v].son[0]=build(1,n,a)]=v;
    233         update(T[v].son[0]);
    234     }
    235  
    236     void Delete(int L,int R)
    237     {
    238         if(L>R)return ;
    239         int u=Select(L-1),v=Select(R+1);
    240         Splay(u,0);
    241         Splay(v,u);
    242         Free(T[v].son[0]);
    243         T[v].son[0]=0;
    244         update(v);
    245     }
    246  
    247     int Get_sum(int L,int R)
    248     {
    249         if(L>R)return 0;
    250         int u=Select(L-1),v=Select(R+1);
    251         Splay(u,0);
    252         Splay(v,u);
    253         if(T[v].son[0])
    254             return T[T[v].son[0]].sum;
    255         else return 0;
    256     }
    257  
    258     int Get_max(int L,int R)
    259     {
    260         if(L>R)return 0;
    261         int u=Select(L-1),v=Select(R+1);
    262         Splay(u,0);
    263         Splay(v,u);
    264         if(T[v].son[0])
    265             return T[T[v].son[0]].mx;
    266         else return 0;
    267     }
    268  
    269     void Free(int x)
    270     {
    271         if(x==0)return ;
    272         Free(T[x].son[0]);
    273         mem.push(x);
    274         Free(T[x].son[1]);
    275     }
    276  
    277     /*void Insert(int &t,int val,int par=0)///普通平衡树,往某个地方的下面插入元素,一般是插入根节点
    278     {
    279         if(t==0)
    280         {
    281             t=++tot;
    282             T[t].init(val);
    283             fa[t]=par;
    284             Splay(tot,0);
    285         }
    286         else
    287         {
    288             int cur=t;
    289             if(val<T[t].val)Insert(T[t].son[0],val,cur);
    290             //else if(val==T[t].val)return ;
    291             else Insert(T[t].son[1],val,cur);
    292             up(cur);
    293         }
    294     }*/
    295  
    296     /*int find(int t,int v)///普通平衡树查找值为v的元素
    297     {
    298         if(t==0)return 0;
    299         else if(T[t].val==v)
    300         {
    301             Splay(t,0);
    302             return t;
    303         }
    304         else if(v<T[t].val)return find(T[t].son[0],v);
    305         else return find(T[t].son[1],v);
    306     }*/
    307  
    308     ///删除根节点元素
    309     /*void Delete()
    310     {
    311         if(!T[root].son[0])
    312         {
    313             fa[T[root].son[1]]=0;
    314             root=T[root].son[1];
    315         }
    316         else
    317         {
    318             int cur=T[root].son[0];
    319             while(T[cur].son[1])cur=T[cur].son[1];
    320             Splay(cur,root);
    321             T[cur].son[1]=T[root].son[1];
    322             root=cur,fa[cur]=0,fa[T[root].son[1]]=root;
    323             up(root);
    324         }
    325     }*/
    326  
    327     int size()
    328     {
    329         return T[root].Size;
    330     }
    331  
    332     ///从t开始找值为v的前驱,返回值
    333     int pred(int t,int v)
    334     {
    335         if(t==0)return v;
    336         else
    337         {
    338             if(v<=T[t].val)return pred(T[t].son[0],v);
    339             else
    340             {
    341                 int ans=pred(T[t].son[1],v);
    342                 if(ans==v)
    343                     ans=T[t].val,Splay(t,0);
    344                 return ans;
    345             }
    346         }
    347     }
    348     ///查找下标t节点的前驱返回下标
    349     int pred(int t)
    350     {
    351         Splay(t,0);
    352         int u=T[t].son[0];
    353         if(u==0)return fa[t];
    354         while(T[u].son[1])u=T[u].son[1];
    355         return u;
    356     }
    357  
    358     ///从t开始找值为v的后继,返回值
    359     int succ(int t,int v)
    360     {
    361         if(t==0)return v;
    362         else
    363         {
    364             if(v>=T[t].val)return succ(T[t].son[1],v);
    365             else
    366             {
    367                 int ans=succ(T[t].son[0],v);
    368                 if(ans==v)
    369                     ans=T[t].val,Splay(t,0);
    370                 return ans;
    371             }
    372         }
    373     }
    374  
    375     ///查找下标t节点的后继返回下标
    376     int succ(int t)
    377     {
    378         Splay(t,0);
    379         int u=T[t].son[1];
    380         if(u==0)return fa[t];
    381         while(T[u].son[0])u=T[u].son[0];
    382         return u;
    383     }
    384  
    385     void Preorder( int t ){///输出成序列顺便检查是否有逻辑错误
    386         if( !t ) return;
    387         pushDown(t);
    388         Preorder( T[t].son[0] );
    389         if(T[t].son[0]&&fa[T[t].son[0]]!=t)
    390             printf("!");
    391         printf("%d " , T[t].val );
    392         Preorder( T[t].son[1] );
    393     }
    394  
    395     /*void init()///普通平衡树初始化
    396     {
    397         T[0].init(-INF);
    398         tot=root=0;
    399     }*/
    400  
    401     void update(int x)///更新下标为x的节点。。手动操作后调用
    402     {
    403         while(x!=0)
    404         pushUp(x),x=fa[x];
    405     }
    406  
    407 };
    408  
    409 Splay_Tree tree;
    410  
    411 int a[N];
    412  
    413 char str[22];
    414  
    415 int main()
    416 {
    417     int n,m;
    418     scanf("%d%d",&n,&m);
    419     for(int i=2;i<=n+1;i++)
    420         scanf("%d",a+i);
    421     tree.init(n+2,a);
    422     int sum=n;
    423     while(m--)
    424     {
    425         scanf("%s",str+1);
    426         if(str[3]=='S')
    427         {
    428             int pos,tot;
    429             scanf("%d%d",&pos,&tot);
    430             pos++;
    431             pos++;
    432             sum+=tot;
    433             for(int i=1;i<=tot;i++)
    434                 scanf("%d",a+i);
    435             tree.Insert(pos,tot,a);
    436         }
    437         else if(str[3]=='L')
    438         {
    439             int pos,tot;
    440             scanf("%d%d",&pos,&tot);
    441             pos++;
    442             tree.Delete(pos,pos+tot-1);
    443             sum-=tot;
    444         }
    445         else if(str[3]=='K')
    446         {
    447             int pos,tot,cov;
    448             scanf("%d%d%d",&pos,&tot,&cov);
    449             pos++;
    450             tree.Cover(pos,pos+tot-1,cov);
    451         }
    452         else if(str[3]=='V')
    453         {
    454             int pos,tot;
    455             scanf("%d%d",&pos,&tot);
    456             pos++;
    457             tree.Reverse(pos,pos+tot-1);
    458         }
    459         else if(str[3]=='T')
    460         {
    461             int pos,tot;
    462             scanf("%d%d",&pos,&tot);
    463             pos++;
    464             printf("%d
    ",tree.Get_sum(pos,pos+tot-1));
    465         }
    466         if(str[3]=='X')
    467         {
    468             printf("%d
    ",tree.Get_max(2,tree.size()-1));
    469         }
    470     }
    471     return 0;
    472 }
    473 
    View Code
  • 相关阅读:
    Docker的安装、配置及其基本使用
    Java提升七:注解
    Java提升六:泛型
    Java提升五:反射与动态代理
    MySQL中如何将主键默认值设为UUID()
    图解Mybatis框架原理及使用
    Java提升四:Stream流
    Java提升三:函数式接口
    Java提升二:Lambda表达式与方法引用
    java提升一:内部类
  • 原文地址:https://www.cnblogs.com/xseventh/p/8585828.html
Copyright © 2011-2022 走看看