NKOJ 3884 (NOI 2005) 维修数列(Splay)

来源:互联网 发布:c语言中函数和 编辑:程序博客网 时间:2024/05/20 02:23

P3884 NOI2005维修数列

问题描述

这里写图片描述

输入格式

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

输出格式

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

样例输入

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

样例输出

-1
10
1
10

提示

你可以认为在任何时刻,数列中至少有 1 个数。 输入数据一定是正确的,即指定位置的数在数列中一定存在。

50%的数据中,任何时刻数列中最多含有 30 000 个数; 100%的数据中,任何时刻数列中最多含有 500 000 个数。

100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件 大小不超过 20MBytes。


Splay模板题,修改和翻转用lazy,维护区间和,考虑如何维护最大区间和,用类似线段树的方法解决即可。
注意当儿子为0时要特别小心。


代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#define N 8000005#define max(a,b) ((a>b)?(a):(b))using namespace std;const int Inf=99999999;int n,m,A[N],L,R;int tot,rt,ls[N],rs[N],fa[N],si[N],v[N],lazy1[N],lazy2[N],lmax[N],rmax[N],Max[N],sum[N];int GM(int x,int y,int z){    if(x>=y&&x>=z)return x;    if(y>=z)return y;    return z;}void MT(int p){    lmax[p]=GM(lmax[ls[p]],sum[ls[p]]+v[p],sum[ls[p]]+v[p]+lmax[rs[p]]);    rmax[p]=GM(rmax[rs[p]],sum[rs[p]]+v[p],sum[rs[p]]+v[p]+rmax[ls[p]]);    Max[p]=GM(Max[ls[p]],Max[rs[p]],max(0,lmax[rs[p]])+max(0,rmax[ls[p]])+v[p]);    sum[p]=sum[ls[p]]+sum[rs[p]]+v[p];    si[p]=si[ls[p]]+si[rs[p]]+1;}void PD(int p){    if(lazy1[p])    {        swap(ls[ls[p]],rs[ls[p]]);        swap(lmax[ls[p]],rmax[ls[p]]);        swap(ls[rs[p]],rs[rs[p]]);        swap(lmax[rs[p]],rmax[rs[p]]);        lazy1[ls[p]]^=1;        lazy1[rs[p]]^=1;    }    if(lazy2[p]!=Inf)    {        v[ls[p]]=v[rs[p]]=lazy2[p];        sum[ls[p]]=lazy2[p]*si[ls[p]];        sum[rs[p]]=lazy2[p]*si[rs[p]];        lmax[ls[p]]=rmax[ls[p]]=Max[ls[p]]=lazy2[p]>0?lazy2[p]*si[ls[p]]:lazy2[p];        lmax[rs[p]]=rmax[rs[p]]=Max[rs[p]]=lazy2[p]>0?lazy2[p]*si[rs[p]]:lazy2[p];        lazy2[ls[p]]=lazy2[rs[p]]=lazy2[p];    }    lazy1[p]=0;lazy2[p]=Inf;}void Zig(int x){    int y=fa[x],z=fa[y];    if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z;    ls[y]=rs[x];fa[rs[x]]=y;    rs[x]=y;fa[y]=x;    MT(y);MT(x);}void Zag(int x){    int y=fa[x],z=fa[y];    if(y==ls[z])ls[z]=x;else rs[z]=x;fa[x]=z;    rs[y]=ls[x];fa[ls[x]]=y;    ls[x]=y;fa[y]=x;    MT(y);MT(x);}void Splay(int x,int t){    int y,z;    while(fa[x]!=t)    {        y=fa[x];z=fa[y];        if(z)PD(z);        if(y)PD(y);        if(x)PD(x);        if(z!=t)        {            if(y==ls[z])            {                if(x==ls[y])Zig(y),Zig(x);                else Zag(x),Zig(x);            }            else            {                if(x==rs[y])Zag(y),Zag(x);                else Zig(x),Zag(x);            }        }        else if(x==ls[y])Zig(x);else Zag(x);    }    if(!t)rt=x;}int BT(int x,int y){    if(x>y)return 0;    int p=++tot;    lazy2[p]=Inf;    if(x==y&&x==0)L=p;    if(x==y&&x==n+1)R=p;    if(x<y)    {        int mid=x+y>>1;        if(mid==0)L=p;        if(mid==n+1)R=p;        v[p]=A[mid];        ls[p]=BT(x,mid-1);        rs[p]=BT(mid+1,y);        fa[ls[p]]=p;        fa[rs[p]]=p;        MT(p);    }    else v[p]=sum[p]=lmax[p]=rmax[p]=Max[p]=A[x],si[p]=1;    return p;}int Find(int k){    int p=rt;    while(p)    {        PD(p);        if(si[ls[p]]+1==k)return p;        if(si[ls[p]]>=k)p=ls[p];        else k-=si[ls[p]]+1,p=rs[p];    }    return p;}void INS(){    int i,x,y,a,b;    scanf("%d%d",&x,&y);    for(i=1;i<=y;i++)scanf("%d",&A[i]);    a=Find(x+1);b=Find(x+2);    Splay(a,0);Splay(b,rt);    tot++;    v[tot]=sum[tot]=lmax[tot]=rmax[tot]=Max[tot]=A[1];    lazy2[tot]=Inf;si[tot]=1;    for(i=2;i<=y;i++)    {        tot++;        v[tot]=A[i];        lazy2[tot]=Inf;        ls[tot]=tot-1;        fa[tot-1]=tot;        MT(tot);    }    fa[tot]=b;ls[b]=tot;MT(b);MT(a);}void DEL(){    int x,y,a,b;    scanf("%d%d",&x,&y);    a=Find(x);b=Find(x+y+1);    Splay(a,0);Splay(b,rt);    fa[ls[rs[rt]]]=0;    ls[rs[rt]]=0;    MT(rs[rt]);    MT(rt);}void CHA(){    int x,y,z,a,b,p;    scanf("%d%d%d",&x,&y,&z);    a=Find(x);b=Find(x+y+1);    Splay(a,0);Splay(b,rt);    p=ls[rs[rt]];    lazy2[p]=z;    v[p]=z;sum[p]=z*si[p];    lmax[p]=rmax[p]=Max[p]=z>0?z*si[p]:z;    MT(rs[rt]);    MT(rt);}void REV(){    int x,y,a,b,p;    scanf("%d%d",&x,&y);    a=Find(x);b=Find(x+y+1);    Splay(a,0);Splay(b,rt);    p=ls[rs[rt]];    lazy1[p]^=1;    swap(ls[p],rs[p]);    swap(lmax[p],rmax[p]);    MT(rs[rt]);    MT(rt);}void SUM(){    int x,y,a,b;    scanf("%d%d",&x,&y);    a=Find(x);b=Find(x+y+1);    Splay(a,0);Splay(b,rt);    printf("%d\n",sum[ls[rs[rt]]]);}void MAX(){    Splay(L,0);Splay(R,rt);    printf("%d\n",Max[ls[rs[rt]]]);}int main(){    int i,x,y,z;char s[15];    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)scanf("%d",&A[i]);    rt=BT(0,n+1);    while(m--)    {        scanf("%s",s);        if(s[2]=='S')INS();        if(s[2]=='L')DEL();        if(s[2]=='K')CHA();        if(s[2]=='V')REV();        if(s[2]=='T')SUM();        if(s[2]=='X')MAX();    }}