zoukankan      html  css  js  c++  java
  • [NOI2005]维护数列

    Description

    Input

    输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
    第2行包含N个数字,描述初始时的数列。
    以下M行,每行一条命令,格式参见问题描述中的表格。
    任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
    插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

    Output

    对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

    Sample Input

    9 8
    2 -6 3 5 1 -5 -3 6 3
    GET-SUM 5 4
    MAX-SUM
    INSERT 8 3 -5 7 2
    DELETE 12 1
    MAKE-SAME 3 3 2
    REVERSE 3 6
    GET-SUM 5 4
    MAX-SUM

    Sample Output

    -1
    10
    1
    10

    HINT

    题解:

    听说做了这道题splay就差不多过关了。(然而我调了一天)

    关于问题中的几个操作:

    1.插入

    将输入的数列用建二叉树的方式建成一棵splay,然后将目标位置的那个节点旋转到根,再将后面那个节点旋转到根的下方(就是split操作),然后就直接将新的splay接到根节点的右子节点的左子节点上。

    2.删除

    也是像之前一样,用split操作将删除的区间确定在根节点的右子节点的左子节点处,然后将删除的区间加入内存池就好了。

    3.修改

    先split一下,然后在根节点的右子节点的左子节点打上修改标记。

    4.旋转

    先split一下,然后在根节点的右子节点的左子节点打上旋转标记。

    5.求和

    先split一下,直接输出根节点右子节点的左子节点的sum。

    6.求和最大的子列

    就像线段树维护一样,对于每一个节点,我们令它所控制的区间是以它为根节点子树,然后维护三个参数ls,rs,ms。分别表示这个区间左边最大的子列,右边最大的子列,中间最大的子列。然后每次push_up的时候跟新一下就好。

    当然这道题目很折磨人,有很多细节:

    1.splay维护区间的时候要在一头一尾加上一个极值,因为如果不加,find可能会找不到

    2.输出和最大的子列的时候也是需要split的,因为两端的极值会对根节点的三个参数造成影响。

    3.push_up和push_down中维护ls,rs,ms的部分有些地方要和0取max,详见代码。

    4.在find中push_down(这个是套路)

      1 //Never forget why you start
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<algorithm>
      8 #include<queue>
      9 #define inf (0x3f3f3f3f)
     10 #define ll(x) bst[x].child[0]
     11 #define rr(x) bst[x].child[1]
     12 #define son(x,t) bst[x].child[t]
     13 using namespace std;
     14 int n,m,cnt;
     15 int pos[1000005],root,a[1000005];
     16 struct Bst{
     17   int child[2],fa,size,sum,x,lazy,round,ls,rs,ms,islazy;
     18 }bst[1000005];
     19 queue<int>mem;
     20 void push_up(int rt){
     21   int l=ll(rt),r=rr(rt);
     22   bst[rt].sum=bst[l].sum+bst[r].sum+bst[rt].x;
     23   bst[rt].size=bst[l].size+bst[r].size+1;
     24   bst[rt].ls=bst[rt].rs=bst[rt].ms=-inf;
     25   bst[rt].ms=max(max(0,bst[l].rs)+bst[rt].x+max(0,bst[r].ls),max(bst[l].ms,bst[r].ms));
     26   bst[rt].rs=max(bst[r].rs,bst[r].sum+bst[rt].x+max(0,bst[l].rs));
     27   bst[rt].ls=max(bst[l].ls,bst[l].sum+bst[rt].x+max(0,bst[r].ls));
     28 }
     29 void rotate(int r,int t){
     30   int fa=bst[r].fa;
     31   son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa;
     32   son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa;
     33   son(r,t)=fa;bst[fa].fa=r;
     34   push_up(fa);
     35   push_up(r);
     36 }
     37 void splay(int r,int goal){
     38   int fa=bst[r].fa;
     39   while(fa!=goal){
     40     if(bst[fa].fa==goal)rotate(r,son(fa,0)==r);
     41     else{
     42       int t=son(bst[fa].fa,0)==fa;
     43       if(son(fa,t)==r)rotate(r,!t),rotate(r,t);
     44       else rotate(fa,t),rotate(r,t);
     45     }
     46     fa=bst[r].fa;
     47   }
     48   if(goal==0)root=r;
     49 }
     50 void push_down(int root){
     51   int l=son(root,0),r=son(root,1);
     52   if(bst[root].round){
     53     bst[l].round^=1;bst[r].round^=1;
     54     swap(son(root,0),son(root,1));
     55     swap(bst[l].ls,bst[l].rs);
     56     swap(bst[r].ls,bst[r].rs);
     57     bst[root].round=0;
     58   }
     59   if(bst[root].islazy){
     60     if(l)bst[l].islazy=1,bst[l].lazy=bst[root].x,bst[l].x=bst[root].x,bst[l].sum=bst[l].size*bst[root].x;
     61     if(r)bst[r].islazy=1,bst[r].lazy=bst[root].x,bst[r].x=bst[root].x,bst[r].sum=bst[r].size*bst[root].x;
     62     if(bst[root].lazy>=0){
     63       bst[l].ls=bst[l].rs=bst[l].ms=bst[l].sum;
     64       bst[r].ls=bst[r].rs=bst[r].ms=bst[r].sum;
     65     }
     66     else{
     67       bst[l].ls=bst[l].rs=bst[l].ms=bst[root].x;
     68       bst[r].ls=bst[r].rs=bst[r].ms=bst[root].x;
     69     }
     70     bst[root].lazy=0;
     71     bst[root].islazy=0;
     72   }
     73 }
     74 int find(int r,int k){
     75   push_down(r);
     76   int y=bst[son(r,0)].size;
     77   if(y+1==k)return r;
     78   else if(y>=k)return find(ll(r),k);
     79   else return find(rr(r),k-y-1);
     80 }
     81 int newnode(){
     82   int pos;
     83   if(!mem.empty())pos=mem.front(),mem.pop();
     84   else pos=++cnt;
     85   bst[pos].child[0]=bst[pos].child[1]=bst[pos].fa=0;
     86   bst[pos].islazy=bst[pos].lazy=bst[pos].round=0;
     87   bst[pos].rs=bst[pos].ls=bst[pos].ms=-inf;
     88   bst[pos].sum=bst[pos].x=0;
     89   bst[pos].size=1;
     90   return pos;
     91 }
     92 void build(int l,int r,int fa,int f){
     93   int mid=(l+r)>>1,now=pos[mid]=newnode();
     94   if(l==r){
     95     bst[now].sum=bst[now].x=a[l];
     96     bst[now].ls=bst[now].rs=bst[now].ms=a[l];
     97   }
     98   if(l<mid)build(l,mid-1,now,mid);
     99   if(mid<r)build(mid+1,r,now,mid);
    100   bst[now].x=a[mid];bst[now].fa=fa;
    101   push_up(now);
    102   son(fa,mid>=f)=now;
    103 }
    104 void insert(int place,int tot){
    105   int i;
    106   for(i=1;i<=tot;i++)
    107     scanf("%d",&a[i]);
    108   build(1,tot,0,0);
    109   int rt=pos[(tot+1)>>1],x=find(root,place),y=find(root,place+1);
    110   splay(x,0);splay(y,x);
    111   son(y,0)=rt;bst[rt].fa=y;
    112   push_up(y);
    113   push_up(x);
    114 }
    115 void clean(int r){
    116   if(r){
    117     mem.push(r);
    118     clean(son(r,0));
    119     clean(son(r,1));
    120   }
    121 }
    122 void delet(int place,int tot){
    123   int x=find(root,place-1),y=find(root,place+tot);
    124   splay(x,0);splay(y,x);
    125   clean(son(y,0));
    126   son(y,0)=0;
    127   push_up(y);push_up(x);
    128 }
    129 void make_same(int place,int tot,int c){
    130   int x=find(root,place-1),y=find(root,place+tot);
    131   splay(x,0);splay(y,x);
    132   int z=son(y,0);
    133   bst[z].sum=c*bst[z].size;
    134   bst[z].lazy=c;
    135   bst[z].islazy=1;
    136   bst[z].x=c;
    137   if(c>=0){
    138     bst[z].ls=bst[z].rs=bst[z].ms=c*bst[z].size;
    139   }
    140   else{
    141     bst[z].ls=bst[z].rs=bst[z].ms=c;
    142   }
    143   push_up(y);push_up(x);
    144 }
    145 void rever(int place,int tot){
    146   int x=find(root,place-1),y=find(root,place+tot);
    147   splay(x,0);splay(y,x);
    148   int z=son(y,0);
    149   bst[z].round^=1;
    150   swap(bst[z].ls,bst[z].rs);
    151   push_up(y);push_up(x);
    152 }
    153 int get_sum(int place,int tot){
    154   int x=find(root,place-1),y=find(root,place+tot);
    155   splay(x,0);splay(y,x);
    156   return bst[son(y,0)].sum;
    157 }
    158 int max_sum(){
    159   int x=find(root,1),y=find(root,bst[root].size);
    160   splay(x,0);splay(y,x);
    161   return bst[son(y,0)].ms;
    162 }
    163 int main(){
    164   int i,j;
    165   scanf("%d%d",&n,&m);
    166   a[1]=-inf;a[n+2]=-inf;
    167   for(i=1;i<=n;i++)
    168     scanf("%d",&a[i+1]);
    169   n+=2;
    170   build(1,n,0,0);
    171   root=pos[(1+n)>>1];
    172   for(i=1;i<=m;i++){
    173     char s[10];int place,tot,c;
    174     scanf("%s",s);
    175     if(s[0]=='I')scanf("%d%d",&place,&tot),insert(place+1,tot);
    176     if(s[0]=='D')scanf("%d%d",&place,&tot),delet(place+1,tot);
    177     if(s[0]=='M'&&s[2]=='K')scanf("%d%d%d",&place,&tot,&c),make_same(place+1,tot,c);
    178     if(s[0]=='R')scanf("%d%d",&place,&tot),rever(place+1,tot);
    179     if(s[0]=='G')scanf("%d%d",&place,&tot),printf("%d
    ",get_sum(place+1,tot));
    180     if(s[0]=='M'&&s[2]=='X')printf("%d
    ",max_sum());
    181   }
    182   return 0;
    183 }
  • 相关阅读:
    cs231n线性分类器作业 svm代码 softmax
    Canopy聚类算法
    python numpy
    thingsboard在windows下安装和使用
    用css布局的方法实现如果字符超过一定长度就显示成省略号
    sql2008以上行转列的方法
    sql 2005,2008开启bcp的方法嗯哈步骤
    关于数据库中的科学计数法的处理
    错误:The Controls collection cannot be modified because the control contains code blocks (i.e. ). .
    ORACLE连接字符串里每个参数的具体意思
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8256758.html
Copyright © 2011-2022 走看看