zoukankan      html  css  js  c++  java
  • bzoj1500 维修数列 splay

    1500: [NOI2005]维修数列

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 10482  Solved: 3234
    [Submit][Status][Discuss]

    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

    终于过了,原来是维护最大子序列合并的时候写错了。。。应该是当前结点最大子序列和等于max(左子结点最大子序列,和右子结点最大子序列,横跨左右的最大子序列和),我居然写成了max(包括左端点的最大子序列,包括右端点的最大子序列,.....)。。。。。
    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define key_val ch[ch[rt][1]][0]
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=500100;
    const int INF=1e9+10;
    const ll MOD=1e9+7;
    
    int N,M;
    int a[maxn];
    char op[20];int pos,n;
    int c[maxn];
    
    int pre[maxn],sz[maxn],ch[maxn][2],rt,tot1;
    int s[maxn],tot2;
    int sum[maxn],val[maxn];
    int ls[maxn],rs[maxn],ms[maxn];
    int cov[maxn],rev[maxn];
    
    int newnode(int &r,int fa,int k)
    {
        if(tot2) r=s[tot2--];
        else r=++tot1;
        pre[r]=fa;val[r]=k;
        sz[r]=1;MS0(ch[r]);
        sum[r]=k;
        cov[r]=rev[r]=0;
        ls[r]=ms[r]=rs[r]=k;
    }
    
    void update_rev(int r)
    {
        if(r==0) return;
        rev[r]^=1;
        swap(ch[r][0],ch[r][1]);
        swap(ls[r],rs[r]);
    }
    
    void update_cov(int r,int c)
    {
        if(r==0) return;
        cov[r]=1;
        sum[r]=c*sz[r];
        val[r]=c;
        ls[r]=rs[r]=ms[r]=max(c,c*sz[r]);
    }
    
    void down(int r)
    {
        if(rev[r]){
            update_rev(ch[r][0]);
            update_rev(ch[r][1]);
            rev[r]=0;
        }
        if(cov[r]){
            update_cov(ch[r][0],val[r]);
            update_cov(ch[r][1],val[r]);
            cov[r]=0;
        }
    }
    
    void up(int r)
    {
        sz[r]=sz[ch[r][0]]+sz[ch[r][1]]+1;
        sum[r]=sum[ch[r][0]]+sum[ch[r][1]]+val[r];
        ls[r]=max(ls[ch[r][0]],sum[ch[r][0]]+val[r]+max(0,ls[ch[r][1]]));
        rs[r]=max(rs[ch[r][1]],sum[ch[r][1]]+val[r]+max(0,rs[ch[r][0]]));
        ms[r]=val[r]+max(rs[ch[r][0]],0)+max(ls[ch[r][1]],0);
        ms[r]=max(ms[r],max(ms[ch[r][0]],ms[ch[r][1]]));
    }
    
    void rot(int x,int kind)
    {
        int y=pre[x];
        down(y);down(x);
        ch[y][kind^1]=ch[x][kind];
        pre[ch[x][kind]]=y;
        if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];
        ch[x][kind]=y;
        pre[y]=x;
        up(y);
    }
    
    void splay(int x,int goal)
    {
        down(x);
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x],z=pre[y];
                int kind=ch[y][0]==x,one=0;
                if(ch[y][0]==x&&ch[z][0]==y) one=1;
                if(ch[y][1]==x&&ch[z][1]==y) one=1;
                if(one) rot(y,kind),rot(x,kind);
                else rot(x,kind),rot(x,kind^1);
            }
        }
        if(goal==0) rt=x;
        up(x);
    }
    
    void rto(int k,int goal)
    {
        int r=rt;k++;
        while(k!=sz[ch[r][0]]+1){
            down(r);
            if(k<sz[ch[r][0]]+1) r=ch[r][0];
            else k-=sz[ch[r][0]]+1,r=ch[r][1];
        }
        splay(r,goal);
    }
    
    void build(int &x,int l,int r,int fa,int *a)
    {
        if(l>r) return;
        int m=(l+r)>>1;
        newnode(x,fa,a[m]);
        build(ch[x][0],l,m-1,x,a);
        build(ch[x][1],m+1,r,x,a);
        up(x);
    }
    
    void Init()
    {
        pre[0]=sz[0]=s[0]=0;MS0(ch[0]);rt=tot1=tot2=0;
        sum[0]=val[0]=cov[0]=rev[0]=0;
        ls[0]=rs[0]=ms[0]=-INF;
        newnode(rt,0,-1);
        newnode(ch[rt][1],rt,-1);
        sz[rt]=2;
        build(key_val,1,N,ch[rt][1],a);
        up(ch[rt][1]);up(rt);
    }
    
    void Rev(int l,int r)
    {
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        update_rev(key_val);
        up(ch[rt][1]);up(rt);
    }
    
    void Cov(int l,int r,int c)
    {
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        update_cov(key_val,c);
        up(ch[rt][1]);up(rt);
    }
    
    void Erase(int r)
    {
        if(r==0) return;
        s[++tot2]=r;
        Erase(ch[r][0]);
        Erase(ch[r][1]);
    }
    
    void Del(int l,int r)
    {
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        Erase(key_val);
        key_val=0;
        up(ch[rt][1]);up(rt);
    }
    
    void Insert(int pos,int n)
    {
        rto(pos,0);
        rto(pos+1,rt);
        down(rt);down(ch[rt][1]);
        build(key_val,1,n,ch[rt][1],c);
        up(ch[rt][1]);up(rt);
    }
    
    int Sum(int l,int r)
    {
        if(l>r) return 0;
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        return sum[key_val];
    }
    
    int Max_sum()
    {
        int l=1,r=sz[rt]-2;
        if(l>r) return 0;
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        return ms[key_val];
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&N,&M)){
            REP(i,1,N) scanf("%d",&a[i]);
            Init();
            //out();
            REP(i,1,M){
                scanf("%s",&op);
                if(op[0]=='I'){
                    scanf("%d%d",&pos,&n);
                    REP(j,1,n) scanf("%d",&c[j]);
                    Insert(pos,n);
                }
                else if(op[0]=='D'){
                    scanf("%d%d",&pos,&n);
                    Del(pos,pos+n-1);
                }
                else if(op[0]=='M'&&op[2]=='K'){
                    scanf("%d%d%d",&pos,&n,&c[0]);
                    Cov(pos,pos+n-1,c[0]);
                }
                else if(op[0]=='R'){
                    scanf("%d%d",&pos,&n);
                    Rev(pos,pos+n-1);
                }
                else if(op[0]=='G'){
                    scanf("%d%d",&pos,&n);
                    printf("%d
    ",Sum(pos,pos+n-1));
                }
                else printf("%d
    ",Max_sum());
            }
        }
        return 0;
    }
    View Code
     
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    实例 find
    实例 历史命令查找
    Crontab
    find命令
    实例 tar备份以日期命名
    断开网络驱动器后图标不消失
    Windows7系统下优化固态硬盘
    目标进程已退出,但未引发 CoreCLR 启动事件
    md5 helper
    List<T> or IList<T>
  • 原文地址:https://www.cnblogs.com/--560/p/5207871.html
Copyright © 2011-2022 走看看