首页 > 题解 > bzoj 1500 [NOI2005]维修数列

bzoj 1500 [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

恶心Treap/Splay模版题。。

前几个操作都很好搞,最后一个的话每一个节点维护一个最大子段和,和从左右子段最大,这样就可以愉快的合并了。

一个else卡了我一天

#include <cstdio>
#include <cstring>
#include <ctime>
#include <queue>
#include <cstdlib>
#define N 500010
#define inf 0x3f3f3f3f
using namespace std;
int ch[N][2],f[N],siz[N],val[N],tmx[N],lmx[N],rmx[N],rev[N],sum[N],cov[N],tar[N];
int inline read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int max(int x,int y){if (x>y) return x;return y;}
int min(int x,int y){if (x<y) return x;return y;}
void swap(int &a,int &b){a^=b,b^=a,a^=b;}
queue<int>trashcan;
int root,cnt;
int new_node(int v)
{
    int x;
    if (!trashcan.empty())
        x=trashcan.front(),trashcan.pop();
    else
        x=++cnt;
    ch[x][0]=ch[x][1]=f[x]=rev[x]=0;
    cov[x]=inf,tar[x]=rand(),siz[x]=1;
    val[x]=sum[x]=tmx[x]=v;
    lmx[x]=rmx[x]=max(v,0);
    return x;
}
void update(int x)
{
    if (ch[x][0] && ch[x][1])
    {
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
        sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
        tmx[x]=max(tmx[ch[x][0]],tmx[ch[x][1]]);
        tmx[x]=max(tmx[x],rmx[ch[x][0]]+val[x]+lmx[ch[x][1]]);
        lmx[x]=max(lmx[ch[x][0]],sum[ch[x][0]]+val[x]+lmx[ch[x][1]]);
        rmx[x]=max(rmx[ch[x][1]],sum[ch[x][1]]+val[x]+rmx[ch[x][0]]);
    }
    else
    if (ch[x][0])
    {
        siz[x]=siz[ch[x][0]]+1;
        sum[x]=sum[ch[x][0]]+val[x];
        tmx[x]=max(tmx[ch[x][0]],rmx[ch[x][0]]+val[x]);
        lmx[x]=max(lmx[ch[x][0]],sum[ch[x][0]]+val[x]);
        lmx[x]=max(0,lmx[x]);
        rmx[x]=max(0,val[x]+rmx[ch[x][0]]);
    }
    else
    if (ch[x][1])
    {
        siz[x]=siz[ch[x][1]]+1;
        sum[x]=sum[ch[x][1]]+val[x];
        tmx[x]=max(tmx[ch[x][1]],lmx[ch[x][1]]+val[x]);
        rmx[x]=max(rmx[ch[x][1]],sum[ch[x][1]]+val[x]);
        rmx[x]=max(0,rmx[x]);
        lmx[x]=max(0,lmx[ch[x][1]]+val[x]);
    }
    else
    {
        siz[x]=1,sum[x]=tmx[x]=val[x];
        lmx[x]=rmx[x]=max(val[x],0);
    }
}
void reverse(int x)
{
    swap(ch[x][0],ch[x][1]);
    swap(lmx[x],rmx[x]);
    rev[x]^=1;
}
void cover(int x,int v)
{
    val[x]=v,sum[x]=siz[x]*v;
    lmx[x]=rmx[x]=max(sum[x],0);
    tmx[x]=max(sum[x],val[x]);
    cov[x]=v;
}
void pushdown(int x)
{
    if (rev[x])
    {
        if (ch[x][0]) reverse(ch[x][0]);
        if (ch[x][1]) reverse(ch[x][1]);
    }
    if (cov[x]!=inf)
    {
        if (ch[x][0]) cover(ch[x][0],cov[x]);
        if (ch[x][1]) cover(ch[x][1],cov[x]);
    }
    rev[x]=0;cov[x]=inf;
}
int build(int *data,int n)
{
    int x,last=0;static int sta[N],top;
    for(int i=1;i<=n;i++)
    {
        x=new_node(data[i]),last=0;
        while(top && tar[sta[top]]>tar[x])
            update(sta[top]),last=sta[top],
            sta[top--]=0;
        if (top)
            ch[sta[top]][1]=x;
        ch[x][0]=last,sta[++top]=x;
    }
    while(top)
        update(sta[top--]);
    return sta[1];
}
void split(int now,int k,int &x,int &y)
{
    if (!now) x=y=0;
    else
    {
        pushdown(now);
        if (siz[ch[now][0]]>=k)
            y=now,split(ch[now][0],k,x,ch[now][0]);
        else
            x=now,split(ch[now][1],k-siz[ch[now][0]]-1,ch[now][1],y);
        update(now);
    }
}
int merge(int x,int y)
{
    if (x) pushdown(x);
    if (y) pushdown(y);
    if (x*y==0) return x+y;
    if (tar[x]<tar[y])
    {
        ch[x][1]=merge(ch[x][1],y);
        update(x);return x;
    }
    else
    {
        ch[y][0]=merge(x,ch[y][0]);
        update(y);return y;
    }
}
void trash(int x)
{
    if (!x) return;
    trashcan.push(x);
    trash(ch[x][0]);
    trash(ch[x][1]);
}
void insert()
{
    int pos=read(),len=read(),x,y;
    static int datas[N];
    for (int i=1;i<=len;i++)
        datas[i]=read();
    int rt=build(datas,len);
    split(root,pos,x,y);
    root=merge(merge(x,rt),y);
}
void delet()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    root=merge(x1,y2);
    trash(y1);
}
void covers()
{
    int pos=read(),len=read(),v=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    cover(y1,v);
    root=merge(x1,merge(y1,y2));
}
void reverses()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    reverse(y1);
    root=merge(x1,merge(y1,y2));
}
void sums()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    printf("%d\n",sum[y1]);
    root=merge(x1,merge(y1,y2));
}
void maxs()
{
    printf("%d\n",tmx[root]);
}
int main()
{
    srand(513);
    static int n=read(),m=read(),a[N];
    for (int i=1;i<=n;i++)
        a[i]=read();
    root=build(a,n);
    static char s[20];
    while (m--)
    {
        scanf("%s",s);
        if (s[0]=='I') insert();
        else if (s[0]=='D') delet();
        else if (s[0]=='M' && s[2] =='K') covers();
        else if (s[0]=='R') reverses();
        else if (s[0]=='G') sums();
        else maxs();
    }
}