[BZOJ 1500][NOI2005]維修數列(Splay)

Description


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


HINT

Solution


開4000000的數組顯然會炸,需要手動回收內存
注意當所有數都是負數的時候maxsum不能一個都不取…
QvQ

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define MAXN 1000010
#define INF 0x3f3f3f3f
#define Max(a,b) (a>b?a:b)
#define lc t[x].ch[0]
#define rc t[x].ch[1]
using namespace std;
int n,m,root,siz=0;
queue<int>q;
struct Node{
    int val,ch[2],father,siz,rev,lazy,sum,lsum,rsum,maxsum;
    Node(){ch[0]=ch[1]=val=father=rev=siz=lazy=sum=lsum=rsum=maxsum=0;}
}t[MAXN];
int num[MAXN];
inline int read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
inline void exchange(int x)
{
    swap(lc,rc);
    swap(t[x].lsum,t[x].rsum);
}
inline void Update(int x)
{
    if(!x)return;
    t[x].siz=t[lc].siz+t[rc].siz+1;
    t[x].sum=t[lc].sum+t[rc].sum+t[x].val;
    t[x].maxsum=t[lc].rsum+t[x].val+t[rc].lsum;
    if(lc)t[x].maxsum=Max(t[x].maxsum,t[lc].maxsum);
    if(rc)t[x].maxsum=Max(t[x].maxsum,t[rc].maxsum);
    t[x].lsum=Max(t[lc].lsum,t[lc].sum+t[x].val+t[rc].lsum);
    t[x].rsum=Max(t[rc].rsum,t[rc].sum+t[x].val+t[lc].rsum);
}
inline void Recycle(int x)
{
    if(!x)return;
    Recycle(lc);Recycle(rc);
    t[x]=Node();q.push(x);
}
inline void Pushdown(int x)
{
    if(!x)return;
    if(t[x].rev)
    {
        t[x].rev=0;
        t[lc].rev^=1;t[rc].rev^=1;
        exchange(lc);exchange(rc);
    }
    if(t[x].lazy)
    {
        t[x].lazy=0;
        if(lc)
        {
            t[lc].val=t[x].val;
            t[lc].lazy=1;
            t[lc].lsum=t[lc].rsum=Max(0,t[lc].siz*t[x].val);
            t[lc].maxsum=Max(t[x].val,t[lc].siz*t[x].val);
            t[lc].sum=t[lc].siz*t[x].val;
        }
        if(rc)
        {
            t[rc].val=t[x].val;
            t[rc].lazy=1;
            t[rc].lsum=t[rc].rsum=Max(0,t[rc].siz*t[x].val);
            t[rc].maxsum=Max(t[x].val,t[rc].siz*t[x].val);
            t[rc].sum=t[rc].siz*t[x].val;
        }
    }
}
inline void Rotate(int x,int &k)
{
    int y=t[x].father;
    int z=t[y].father;
    int p=(t[y].ch[0]==x)?0:1;
    if(y==k)k=x;
    else
    {
        if(t[z].ch[0]==y)t[z].ch[0]=x;
        else t[z].ch[1]=x;
    }
    t[x].father=z;
    t[y].ch[p]=t[x].ch[p^1];
    t[t[x].ch[p^1]].father=y;
    t[x].ch[p^1]=y;
    t[y].father=x;
    Update(y),Update(x);
}
inline void Splay(int x,int &k)
{
    while(x!=k)
    {
        int y=t[x].father;
        int z=t[y].father;
        if(y!=k)
        {
            if((t[y].ch[0]==x)^(t[z].ch[0]==y))
            Rotate(x,k);
            else Rotate(y,k); 
        }
        Rotate(x,k);
    }
}
inline int Build(int l,int r,int f)
{
    if(r<l)return 0;
    int now=q.front();q.pop();
    int mid=(l+r)/2;
    t[now].val=num[mid];
    t[now].father=f;
    if(l==r)
    {
        t[now].lsum=t[now].rsum=Max(0,t[now].val);
        t[now].maxsum=t[now].sum=t[now].val;
        t[now].siz=1;return now;;
    }
    t[now].ch[0]=Build(l,mid-1,now);
    t[now].ch[1]=Build(mid+1,r,now);
    Update(now);
    return now;
}
inline int Find(int x,int k)
{
    if(!x)return 0;
    Pushdown(x);
    if(k<=t[lc].siz)return Find(lc,k);
    if(k>t[lc].siz+1)return Find(rc,k-t[lc].siz-1);
    return x;
}
int main()
{
    for(int i=1;i<MAXN;i++)q.push(i);
    n=read();m=read();
    for(int i=1;i<=n;i++)
    num[i+1]=read();
    num[1]=num[n+2]=-INF;
    root=Build(1,n+2,0);
    for(int i=1;i<=m;i++)
    {
        char opt[15];
        int pos,tot,c,x,y,R,p;
        scanf("%s",opt);
        switch(opt[0])
        {
            case 'I':
                pos=read();tot=read();
                for(int i=1;i<=tot;i++)
                num[i]=read();
                x=Find(root,pos+1);
                y=Find(root,pos+2);
                Splay(x,root);Splay(y,t[root].ch[1]);
                R=Build(1,tot,y);
                t[y].ch[0]=R;
                Update(y);Update(x);
                break;
            case 'D':
                pos=read();tot=read();
                x=Find(root,pos);
                y=Find(root,pos+tot+1);
                Splay(x,root);Splay(y,t[root].ch[1]);
                Recycle(t[y].ch[0]);
                t[y].ch[0]=0;
                Update(y);Update(x);
                break;
            case 'M':
                if(opt[2]=='K')
                {
                    pos=read();tot=read();c=read();
                    x=Find(root,pos);
                    y=Find(root,pos+tot+1);
                    Splay(x,root);Splay(y,t[root].ch[1]);
                    p=t[y].ch[0];
                    t[p].rev=0;t[p].lazy=1;t[p].val=c;
                    t[p].lsum=t[p].rsum=Max(0,c*t[p].siz);
                    t[p].maxsum=t[p].sum=c*t[p].siz;
                    Update(y);Update(x);
                }
                else if(opt[2]=='X')
                printf("%d\n",t[root].maxsum);
                break;
            case 'R':
                pos=read();tot=read();
                x=Find(root,pos);
                y=Find(root,pos+tot+1);
                Splay(x,root);Splay(y,t[root].ch[1]);
                p=t[y].ch[0];
                if(!t[p].lazy){
                    t[p].rev^=1;
                    exchange(p);
                    Update(y);Update(x);
                }
                break;
            case 'G':
                pos=read();tot=read();
                x=Find(root,pos);
                y=Find(root,pos+tot+1);
                Splay(x,root);Splay(y,t[root].ch[1]);
                p=t[y].ch[0];
                printf("%d\n",t[p].sum);
                break;
        }
    }
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章