bzoj:1500: [NOI2005]维修数列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

HINT

 

技术分享

 

技术分享

 

总算切掉了这SPLAY神题……

主要就是得每次挪个根,把要操作的区间卡成一颗完整的子树就好啦!

细节还是调了挺久…= =…没办法,弱嘛...>_<

一开始以为回收空间会很麻烦,结果还是开个queue把删掉的节点遍历一遍放进去就完了。

 

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

queue <int> qh;
int n,m,l,r,p,ch,a[500000],pos,tot,u,c,f;
inline int read(){
    p=0;ch=getchar();f=1;
    while(ch<0||ch>9) {if (ch==-) f=-1;ch=getchar();}
    while(ch>=0&&ch<=9) p=p*10+ch-48,ch=getchar();
    return p*f;
}
struct tree{
    int l,r,k,f,s,c,sum,lx,rx,mx;
    bool bo;
    tree(){
        bo=f=l=r=sum=0;
        c=1001;
    }
};
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
struct splay_tree{
    int size,root;
    tree t[500001];
    splay_tree(){
        size=0;root=0;
    }
    inline void update(int p){
        t[p].s=t[t[p].l].s+t[t[p].r].s+1;
        t[p].sum=t[p].k+t[t[p].l].sum+t[t[p].r].sum;
        t[p].lx=max(t[t[p].l].lx,t[t[p].r].lx+t[t[p].l].sum+t[p].k);
        t[p].rx=max(t[t[p].r].rx,t[t[p].l].rx+t[t[p].r].sum+t[p].k);
        t[p].mx=max(max(t[t[p].l].mx,t[t[p].r].mx),t[t[p].l].rx+t[t[p].r].lx+t[p].k);
    }
    inline void pd(int x){
        if (t[x].bo){
            t[t[x].l].bo^=1;t[t[x].r].bo^=1;
            swap(t[x].l,t[x].r);
            swap(t[x].lx,t[x].rx);
            t[x].bo=0;
        }
        if (t[x].c!=1001){
            t[x].k=t[x].c;
            t[t[x].l].c=t[t[x].r].c=t[x].c;
            t[x].sum=t[x].c*t[x].s;
            if (t[x].c>=0) t[x].lx=t[x].rx=t[x].mx=t[x].sum;else t[x].lx=t[x].rx=0,t[x].mx=t[x].c;
            t[x].c=1001;
        }
    }
    inline void ler(int &p){
        int k=t[p].r;
        t[k].f=t[p].f;
        t[p].f=k;
        t[t[k].l].f=p;
        t[p].r=t[k].l;
        t[k].l=p;
        update(p);update(k);
        p=k;
    }
    inline void rir(int &p){
        int k=t[p].l;
        t[k].f=t[p].f;
        t[p].f=k;
        t[t[k].r].f=p;
        t[p].l=t[k].r;
        t[k].r=p;
        update(p);update(k);
        p=k;
    }
    inline void ph(int &p,bool bo){
        if (bo) rir(p);else ler(p);
    }
    inline bool gc(int p){return t[t[p].f].l==p;}
    inline void rot(int p){
        if (t[p].f==root) ph(root,gc(p));else
        if (gc(t[p].f)) ph(t[t[t[p].f].f].l,gc(p));else ph(t[t[t[p].f].f].r,gc(p));
    }
    inline void splay(int p,int f){
        while(t[p].f!=f){
            if (t[t[p].f].f==f) rot(p);else
            if (gc(t[p].f)==gc(p)) rot(t[p].f),rot(p);else rot(p),rot(p);
        }
    }
    inline void build(int &p,int l,int r){
        if (l>r) return;
        if (!qh.empty()) p=qh.front(),qh.pop();else p=++size;
        int mid=(l+r)>>1;
        t[p].k=a[mid];
        build(t[p].l,l,mid-1);
        build(t[p].r,mid+1,r);
        t[t[p].l].f=t[t[p].r].f=p;
        if (l==r){
            t[p].sum=a[mid];
            if (a[mid]>=0) t[p].lx=t[p].rx=a[mid];else t[p].lx=t[p].rx=0;
            t[p].mx=a[mid];
            t[p].s=1;
        }else update(p);
    }
    inline int find(int x,int y){
        pd(x);
        pd(t[x].l);pd(t[x].r);update(x);
        if (t[t[x].l].s<y-1) return find(t[x].r,y-1-t[t[x].l].s);
        if (t[t[x].l].s==y-1) return x;
        return find(t[x].l,y);
    }
    inline void in(int x,int n){
        u=find(root,x+2);x=find(root,x+1);
        splay(x,0);splay(u,x);
        build(t[u].l,1,n);
        t[t[u].l].f=u;
        update(u);update(x);
    }
    inline void reuse(int x){
        if (!x) return;
        qh.push(x);
        reuse(t[x].l);reuse(t[x].r);
        t[x].l=t[x].r=t[x].bo=0;t[x].c=1001;
    }
    inline void del(int x,int n){
        u=find(root,x);x=find(root,x+n+1);
        splay(u,0);splay(x,u);
        reuse(t[x].l);
        t[x].l=0;
        update(x);update(u);
    }
    inline void change(int x,int n,int c){
        u=find(root,x);x=find(root,x+n+1);
        splay(u,0);splay(x,u);
        t[t[x].l].c=c;
        pd(t[x].l);
        update(x);update(u);
    }
    inline void turn(int x,int n){
        u=find(root,x);x=find(root,x+n+1);
        splay(u,0);splay(x,u);
        t[t[x].l].bo^=1;
        pd(t[x].l);
        update(x);update(u);
    }
    inline int qu(int x,int n){
        u=find(root,x);x=find(root,x+n+1);
        splay(u,0);splay(x,u);
        return t[t[x].l].sum;
        update(x);update(u);
    }
}t;
char ss[20];
int main(){
    register int i;
    n=read();m=read();
    for (i=1;i<=n;i++) a[i]=read();
    a[0]=-1e8;a[n+1]=-1e8;
    t.build(t.root,0,n+1);
    while(m--)
    {
        scanf("%s",ss);
        if (ss[0]==I){
            pos=read();tot=read();
            for (i=1;i<=tot;i++) a[i]=read();
            t.in(pos,tot);
        }else if (ss[0]==D) pos=read(),tot=read(),t.del(pos,tot);
        else if (ss[0]==M){
            if (ss[2]==K) pos=read(),tot=read(),c=read(),t.change(pos,tot,c);
            else printf("%d\n",t.t[t.root].mx);
        }else if (ss[0]==R) pos=read(),tot=read(),t.turn(pos,tot);
        else if (ss[0]==G) pos=read(),tot=read(),printf("%d\n",t.qu(pos,tot));
    }
}

 

 

 

 

以上是关于bzoj:1500: [NOI2005]维修数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj:1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列[splay ***]

BZOJ1500[NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

bzoj1500 [NOI2005]维修数列

bzoj1500: [NOI2005]维修数列