JZOJ 2413. 【NOI2005】维护数列

来源:互联网 发布:晕血学生物 知乎 编辑:程序博客网 时间:2024/06/05 22:02

Description

  请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格)
  1. 插入 INSERT_posi_tot_c1_c2_…_ctot 在当前数列的第posi个数字后插入tot个数字:c1, c2, …, ctot;若在数列首插入,则posi为0
  2. 删除 DELETE_posi_tot 从当前数列的第posi个数字开始连续删除tot个数字
  3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第posi个数字开始的连续tot个数字统一修改为c
  4. 翻转 REVERSE_posi_tot 取出从当前数列的第posi个数字开始的tot个数字,翻转后放入原来的位置
  5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第posi个数字开始的tot个数字的和并输出
  6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和

Input

  输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。
  第2行包含N个数字,描述初始时的数列。
  以下M行,每行一条命令,格式参见问题描述中的表格。

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

Data Constraint

Hint

样例说明请点这里
【数据规模和约定】
  你可以认为在任何时刻,数列中至少有1个数。
  输入数据一定是正确的,即指定位置的数在数列中一定存在。
  50%的数据中,任何时刻数列中最多含有30 000个数;
  100%的数据中,任何时刻数列中最多含有500 000个数。
  100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
  100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Solution

  • 这题真的调试了一万年……

  • 经典的Splay操作,维护子序列的话就维护一下子树前后缀的最大值,在合并到父亲上即可。

Code

#include<cstdio>#include<algorithm>using namespace std;const int N=5e5+3,inf=1e9;int root,tot;int a[N],fa[N],key[N],size[N],s[N][2];int sum[N],c[N],mx[N],pre[N],suf[N],back[N];bool rev[N];inline int read(){    int X=0,w=1; char ch=0;    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();    return X*w;}inline void write(int x){    if(x<0) x=-x,putchar('-');    if(x>9) write(x/10);    putchar(x%10+'0');}inline int max(int x,int y){    return x>y?x:y;}inline bool pd(int x){    return x==s[fa[x]][1];}inline void newnode(int &v,int val,int p){    if(back[0]) v=back[back[0]--]; else v=++tot;    sum[v]=mx[v]=key[v]=val;    pre[v]=suf[v]=max(0,val);    size[v]=1,fa[v]=p,c[v]=inf;    s[v][0]=s[v][1]=rev[v]=0;}inline void reverse(int v){    if(!v) return;    swap(s[v][0],s[v][1]);    swap(pre[v],suf[v]);    rev[v]^=1;}inline void modify(int v,int val){    if(!v) return;    sum[v]=size[v]*val,c[v]=key[v]=val;    if(val>0) mx[v]=pre[v]=suf[v]=sum[v]; else        pre[v]=suf[v]=0,mx[v]=val;}inline void update(int v){    sum[v]=sum[s[v][0]]+sum[s[v][1]]+key[v];    size[v]=size[s[v][0]]+size[s[v][1]]+1;    pre[v]=max(pre[s[v][0]],sum[s[v][0]]+key[v]+pre[s[v][1]]);    suf[v]=max(suf[s[v][1]],sum[s[v][1]]+key[v]+suf[s[v][0]]);    mx[v]=max(0,suf[s[v][0]])+key[v]+max(0,pre[s[v][1]]);    if(s[v][0]) mx[v]=max(mx[v],mx[s[v][0]]);    if(s[v][1]) mx[v]=max(mx[v],mx[s[v][1]]);}inline void down(int v){    if(rev[v])    {        reverse(s[v][0]),reverse(s[v][1]);        rev[v]=false;    }    if(c[v]<inf)    {        modify(s[v][0],c[v]),modify(s[v][1],c[v]);        c[v]=inf;    }}inline void build(int &v,int l,int r,int p){    if(l>r) return;    int mid=(l+r)>>1;    newnode(v,a[mid],p);    build(s[v][0],l,mid-1,v);    build(s[v][1],mid+1,r,v);    update(v);}inline void rotate(int x){    down(x);    int y=fa[x],w=pd(x);    if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y;    if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;    s[fa[y]=x][w^1]=y;    update(y);}inline void splay(int x,int k){    for(int y;(y=fa[x])^k;rotate(x))        if(fa[y]^k) rotate(pd(x)==pd(y)?y:x);    update(x);    if(!k) root=x;}inline int kth(int v,int k){    down(v);    if(size[s[v][0]]+1==k) return v;    if(k<=size[s[v][0]]) return kth(s[v][0],k);    return kth(s[v][1],k-size[s[v][0]]-1);}inline void change(int l,int r,int val){    splay(kth(root,l-1),0);    splay(kth(root,r+1),root);    modify(s[s[root][1]][0],val);}inline int get_sum(int l,int r){    splay(kth(root,l-1),0);    splay(kth(root,r+1),root);    return sum[s[s[root][1]][0]];}inline void insert(int x,int y){    splay(kth(root,x),0);    splay(kth(root,x+1),root);    build(s[s[root][1]][0],1,y,s[root][1]);    update(s[root][1]),update(root);}inline void travel(int v){    down(v);    if(s[v][0]) travel(s[v][0]);    back[++back[0]]=v;    if(s[v][1]) travel(s[v][1]);}inline void delete_num(int x,int y){    splay(kth(root,x-1),0);    splay(kth(root,y+1),root);    travel(s[s[root][1]][0]);    s[s[root][1]][0]=0;    update(s[root][1]),update(root);}inline void flip(int l,int r){    splay(kth(root,l-1),0);    splay(kth(root,r+1),root);    reverse(s[s[root][1]][0]);}inline int get_max(int l,int r){    splay(kth(root,l-1),0);    splay(kth(root,r+1),root);    return mx[s[s[root][1]][0]];}inline void print(int v){    down(v);    if(s[v][0]) print(s[v][0]);    if(key[v]<inf) write(key[v]),putchar(' ');    if(s[v][1]) print(s[v][1]);}int main(){    int n=read(),m=read();    a[1]=a[n+2]=-inf,c[0]=inf;    for(int i=2;i<=n+1;i++) a[i]=read();    build(root,1,n+2,0);    while(m--)    {        char ch=getchar();        while(ch!='X' && ch!='G' && ch!='V' && ch!='I' && ch!='D' && ch!='K') ch=getchar();        if(ch=='K')//MAKE-SAME        {            getchar(),getchar();            int x=read()+1,y=x+read()-1;            change(x,y,read());        }else        if(ch=='G')//GET-SUM        {            getchar(),getchar(),getchar();            int x=read()+1,y=x+read()-1;            write(get_sum(x,y)),putchar('\n');        }else        if(ch=='I')//INSERT        {            int x=read()+1,y=read();            for(int i=1;i<=y;i++) a[i]=read();            insert(x,y);        }else        if(ch=='D')//DELETE        {            int x=read()+1,y=x+read()-1;            delete_num(x,y);         }else        if(ch=='V')//REVERSE        {            int x=read()+1,y=x+read()-1;            flip(x,y);        }else        if(ch=='X')//MAX-SUM        {            write(get_max(2,size[root]-1)),putchar('\n');            scanf("\n");        }    }    return 0;}