zoukankan      html  css  js  c++  java
  • [NOI2005]维护数列

    bzoj1500 [NOI2005]维护数列

    题目描述:

    请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)

    输入输出格式

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

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

    输入输出样例

    输入样例#1:

    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:

    -1
    10
    1
    10
    

    说明

    你可以认为在任何时刻,数列中至少有 1 个数。

    输入数据一定是正确的,即指定位置的数在数列中一定存在。

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

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

    100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。

    100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。

    题解:
    对于前5个操作,直接按照splay操作进行
    第6个操作,记录左起最长序列、右起最长序列和这个区间的最长序列,合并时通过左右合并
    为防止MLE,需要把树上被删除节点回收

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<set>
    #include<bitset>
    #include<sstream>
    #include<cstdlib>
    #define QAQ int
    #define TAT long long
    #define OwO bool
    #define ORZ double
    #define F(i,j,n) for(QAQ i=j;i<=n;++i)
    #define E(i,j,n) for(QAQ i=j;i>=n;--i)
    #define MES(i,j) memset(i,j,sizeof(i))
    #define MEC(i,j) memcpy(i,j,sizeof(j))
    
    using namespace std;
    const QAQ N=1000010;
    const QAQ Big=1e6;
    
    QAQ n,m,js,rot,a[N>>1],id[N>>1];
    struct data{
        QAQ fa,son[2],sum;
        QAQ val,size,mx,lx,rx;
        OwO rev,lset;
    }tree[N];
    queue<QAQ> q;
    char s[15];
    
    void push_up(QAQ o){
        QAQ l=tree[o].son[0],r=tree[o].son[1];
        tree[o].sum=tree[l].sum+tree[r].sum+tree[o].val;
        tree[o].size=tree[l].size+tree[r].size+1;
        tree[o].mx=max(max(tree[l].mx,tree[r].mx),tree[l].rx+tree[r].lx+tree[o].val);
        tree[o].lx=max(tree[l].lx,tree[l].sum+tree[r].lx+tree[o].val);
        tree[o].rx=max(tree[r].rx,tree[r].sum+tree[l].rx+tree[o].val);
    }
    
    void push_down(QAQ o){
        QAQ l=tree[o].son[0],r=tree[o].son[1];
        if(tree[o].lset){
            tree[o].lset=tree[o].rev=0;
            if(l) {tree[l].lset=1;tree[l].val=tree[o].val;tree[l].sum=tree[l].size*tree[l].val;}
            if(r) {tree[r].lset=1;tree[r].val=tree[o].val;tree[r].sum=tree[r].size*tree[r].val;}
            if(tree[o].val>=0){
                if(l) tree[l].lx=tree[l].rx=tree[l].mx=tree[l].sum;
                if(r) tree[r].lx=tree[r].rx=tree[r].mx=tree[r].sum;
            }
            else {
                if(l) tree[l].lx=tree[l].rx=0,tree[l].mx=tree[l].val;
                if(r) tree[r].lx=tree[r].rx=0,tree[r].mx=tree[r].val;
            }
        }
        if(tree[o].rev){
            tree[o].rev=0;tree[l].rev^=1;tree[r].rev^=1;
            swap(tree[l].lx,tree[l].rx);swap(tree[r].lx,tree[r].rx);
            swap(tree[l].son[0],tree[l].son[1]);
            swap(tree[r].son[0],tree[r].son[1]);
        }
    }
    
    void build(QAQ l,QAQ r,QAQ fa){
        if(l>r) return ;
        QAQ mid=l+r>>1,o=id[mid];
        if(l==r){
            tree[o].mx=tree[o].sum=a[l];
            tree[o].lset=tree[o].rev=0;
            tree[o].lx=tree[o].rx=max(a[l],0);
            tree[o].size=1;
        }
        build(l,mid-1,mid);build(mid+1,r,mid);
        tree[o].val=a[mid];tree[o].fa=id[fa];
        push_up(o);
        tree[id[fa]].son[mid>=fa]=o;
    }
    
    QAQ find(QAQ o,QAQ x){
        push_down(o);
        if(tree[tree[o].son[0]].size+1==x) return o;
        else if(tree[tree[o].son[0]].size>=x) return find(tree[o].son[0],x);
        else return find(tree[o].son[1],x-tree[tree[o].son[0]].size-1);
    }
    
    OwO get(QAQ o){return tree[tree[o].fa].son[1]==o;}
    void rotate(QAQ o){
        QAQ fa=tree[o].fa,ff=tree[fa].fa;
        OwO pd=get(o);
        if(ff) tree[ff].son[get(fa)]=o;
        tree[o].fa=ff;
        tree[fa].son[pd]=tree[o].son[1-pd];
        tree[tree[o].son[1-pd]].fa=fa;
        tree[fa].fa=o;tree[o].son[1-pd]=fa;
        push_up(fa);push_up(o);
    }
    
    void splay(QAQ o,QAQ goal){
        while(tree[o].fa!=goal){
            QAQ fa=tree[o].fa,ff=tree[fa].fa;
            if(ff!=goal) if(tree[ff].son[1]==fa ^ tree[fa].son[1]==o) rotate(o);
                        else rotate(fa);
            rotate(o);
        }
        if(!goal) rot=o;
        push_up(o);
    }
    
    void Insert(QAQ p,QAQ tot){
        F(i,1,tot) scanf("%d",&a[i]);
        F(i,1,tot) if(q.size()) id[i]=q.front(),q.pop();
        else id[i]=++js;
        build(1,tot,0);
        QAQ l=find(rot,p+1),r=find(rot,p+2);
        splay(l,0);splay(r,l);
        QAQ rt=id[1+tot>>1];
        tree[rt].fa=r;tree[r].son[0]=rt;
        push_up(r);push_up(l);
    }
    
    QAQ split(QAQ p,QAQ tot){
        QAQ l=find(rot,p),r=find(rot,p+tot+1);
        splay(l,0);
        splay(r,l);
        return tree[r].son[0];
    }
    
    void recovery(QAQ o){
        if(tree[o].son[0]) recovery(tree[o].son[0]);
        if(tree[o].son[1]) recovery(tree[o].son[1]);
        q.push(o);
        tree[o].fa=tree[o].son[0]=tree[o].son[1]=tree[o].lset=tree[o].rev=0;
    }
    
    void Del(QAQ p,QAQ tot){
        QAQ o=split(p,tot);
        QAQ fa=tree[o].fa;
        recovery(o);
        tree[fa].son[0]=0;
        push_up(fa);push_up(tree[fa].fa);
    }
    
    void change(QAQ p,QAQ tot,QAQ x){
        QAQ o=split(p,tot);
        tree[o].val=x;tree[o].lset=1;
        tree[o].sum=tree[o].val*tree[o].size;
        if(tree[o].val>=0) tree[o].lx=tree[o].rx=tree[o].mx=tree[o].sum;
        else tree[o].lx=tree[o].rx=0,tree[o].mx=tree[o].val;
        push_up(tree[o].fa);push_up(tree[tree[o].fa].fa);
    }
    
    void reverse(QAQ p,QAQ tot){
        QAQ o=split(p,tot);
        if(!tree[o].lset){
            tree[o].rev^=1;
            swap(tree[o].son[0],tree[o].son[1]);
            swap(tree[o].lx,tree[o].rx);
            push_up(tree[o].fa);
            push_up(tree[tree[o].fa].fa);
        }
    }
    
    QAQ get_sum(QAQ p,QAQ tot){
        QAQ o=split(p,tot);
        return tree[o].sum;
    }
    
    QAQ main(){
        scanf("%d%d",&n,&m);
        F(i,2,n+1) scanf("%d",&a[i]),id[i]=i;
        tree[0].mx=a[1]=a[n+2]=-Big;
        id[1]=1;id[n+2]=n+2;
        build(1,n+2,0);
        rot=n+3>>1;js=n+2;
        while(m--){
            scanf("%s",s+1);
            if(s[1]=='I'){
                QAQ p,tot;
                scanf("%d%d",&p,&tot);
                Insert(p,tot);
            }
            else if(s[1]=='D'){
                QAQ p,tot;
                scanf("%d%d",&p,&tot);
                Del(p,tot);
            }
            else if(s[1]=='M'&&s[3]=='K'){
                QAQ p,tot,x;
                scanf("%d%d%d",&p,&tot,&x);
                change(p,tot,x);
            }
            else if(s[1]=='R'){
                QAQ p,tot;
                scanf("%d%d",&p,&tot);
                reverse(p,tot);
            }
            else if(s[1]=='G'){
                QAQ p,tot;
                scanf("%d%d",&p,&tot);
                printf("%d
    ",get_sum(p,tot));
            }
            else printf("%d
    ",tree[rot].mx);
        }
        return 0;
    }
    
  • 相关阅读:
    linux运维、架构之路-K8s中部署Jenkins集群高可用
    linux运维、架构之路-K8s数据管理
    linux运维、架构之路-K8s通过Service访问Pod
    linux运维、架构之路-K8s应用
    linux运维、架构之路-K8s健康检查Health Check
    linux运维、架构之路-K8s滚动更新及回滚
    linux运维、架构之路-Kubernetes基础(一)
    Python前端HTML
    linux运维、架构之路-Kubernetes离线集群部署-无坑
    linux运维、架构之路-MongoDB单机部署
  • 原文地址:https://www.cnblogs.com/heower/p/8746974.html
Copyright © 2011-2022 走看看