zoukankan      html  css  js  c++  java
  • bzoj1500: [NOI2005]维修数列 (Splay+变态题)

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 11353  Solved: 3553
    [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

    思路:最后一个操作一开始做的时候我是直接用dp[i]=max(dp[i-1]+a[i],a[i])做的,这样每次操作都要花O(n)的复杂度,一直T,后来看了别人的思路,发现这个也是要记录的(= =还是太稚嫩)。除了在splay上面维护pre[],sz[],ch[][2]等一些基本的东西外,还要维护zhi[](这个节点的值),sum[](这个节点代表的区间的和),rev[](旋转标记),same[](区间内都为同一个数的标记),lx[](这个节点所代表的区间从以左端点为起点的最大和),rx[](~从以右端点为起点的最大和),mx[](这个区间子区间的最大和)。然后就是splay经典操作了,这题一开始写的时候没有用内存池,即没有回收删除的点,一直T,应该是内存不够导致的吧。后来看了kuangbin大神的模板,回收废的节点后才过了。ps:kuangbin大神的splay模板太劲了!


    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define Key_value ch[ch[rt][1]][0]
    #define maxn 1000010
    int n;
    int cnt,rt;
    int pre[maxn],ch[maxn][2],sz[maxn],rev[maxn],zhi[maxn],sum[maxn],same[maxn];
    int lx[maxn],rx[maxn],mx[maxn];
    int b[maxn],tot2;//内存池和容量
    int a[maxn];
    
    void update_same(int x,int c)
    {
        if(!x)return;
        zhi[x]=c;
        sum[x]=c*sz[x];
        lx[x]=rx[x]=mx[x]=max(c,c*sz[x]);
        same[x]=1;
    }
    
    void update_rev(int x)
    {
        if(!x)return;       //!!!
        rev[x]^=1;
        swap(ch[x][0],ch[x][1]);
        swap(lx[x],rx[x]);
    }
    void pushdown(int x)
    {
        int y;
        if(rev[x]){
            update_rev(ch[x][0]);
            update_rev(ch[x][1]);
            rev[x]=0;
        }
        if(same[x]){
            update_same(ch[x][0],zhi[x]);
            update_same(ch[x][1],zhi[x]);
            same[x]=0;
        }
    }
    void pushup(int x)
    {
        int lson=ch[x][0],rson=ch[x][1];
        sz[x]=sz[lson]+sz[rson]+1;
        sum[x]=sum[lson]+sum[rson]+zhi[x];
        lx[x]=max(lx[lson],sum[lson]+zhi[x]+max(0,lx[rson]) ); //!!!max(0,lx[rson])
        rx[x]=max(rx[rson],sum[rson]+zhi[x]+max(0,rx[lson]) );
        mx[x]=max(mx[lson],mx[rson]);
        mx[x]=max(mx[x],max(0,rx[lson])+zhi[x]+max(0,lx[rson]) );
    }
    void Treavel(int x)
    {
        if(x)
        {
            pushdown(x);
            Treavel(ch[x][0]);
            printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d zhi = %2d sum=%2d
    ",x,ch[x][0],ch[x][1],pre[x],sz[x],zhi[x],sum[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug()
    {
        printf("root:%d
    ",rt);
        Treavel(rt);
    }
    
    void newnode(int &x,int father,int value)
    {
        if(tot2)x=b[tot2--];
        else x=++cnt;
        pre[x]=father;ch[x][0]=ch[x][1]=0;sz[x]=1;rev[x]=0;zhi[x]=value;sum[x]=value;same[x]=0;
        lx[x]=rx[x]=mx[x]=value;
    }
    
    void build(int &x,int l,int r,int father)
    {
        if(l>r)return;
        int mid=(l+r)/2;
        newnode(x,father,a[mid]);
        build(ch[x][0],l,mid-1,x);
        build(ch[x][1],mid+1,r,x);
        pushup(x);
    }
    
    void init()
    {
        cnt=rt=0;
        pre[rt]=ch[rt][0]=ch[rt][1]=sz[rt]=0;
        rev[rt]=zhi[rt]=sum[rt]=same[rt]=0;
        lx[rt]=rx[rt]=mx[rt]=-inf;
    
        newnode(rt,0,-10000);
        newnode(ch[rt][1],rt,-10000);
        build(Key_value,1,n,ch[rt][1]);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    void rotate(int x,int p)
    {
        int y=pre[x];
        pushdown(y);pushdown(x);
        ch[y][!p]=ch[x][p];
        pre[ch[x][p] ]=y;
        if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x;
        pre[x]=pre[y];
        ch[x][p]=y;
        pre[y]=x;
        pushup(y);pushup(x);
    }
    void splay(int x,int goal)
    {
        pushdown(x);
        while(pre[x]!=goal){
            if(pre[pre[x] ]==goal){
                pushdown(pre[x]);pushdown(x);
                rotate(x,ch[pre[x]][0]==x);
            }
            else{
                int y=pre[x];int z=pre[y];
                pushdown(z);pushdown(y);pushdown(x);
                int p=ch[pre[y] ][0]==y;
                if(ch[y][p]==x )rotate(x,!p);
                else rotate(y,p);
                rotate(x,p);
            }
        }
        if(goal==0)rt=x;
        pushup(x);
    }
    
    int get_kth(int x,int k)
    {
        int i,j;
        pushdown(x);
        int t=sz[ch[x][0] ]+1;
        if(t==k)return x;
        if(t<k)return get_kth(ch[x][1],k-t);
        return get_kth(ch[x][0],k);
    }
    
    void Insert(int pos,int tot)
    {
        int i,j;
        for(i=1;i<=tot;i++){
            scanf("%d",&a[i]);
        }
        splay(get_kth(rt,pos+1),0);
        splay(get_kth(rt,pos+2),rt);
        build(Key_value,1,tot,ch[rt][1]);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    
    void erase(int x)
    {
        if(x==0)return; //!!!
        b[++tot2]=x;
        erase(ch[x][0]);
        erase(ch[x][1]);
    }
    
    void Delete(int pos,int tot)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        erase(Key_value);
        Key_value=0;
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    void Make_same(int pos,int tot,int c)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        update_same(Key_value,c);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    void Reverse(int pos,int tot)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        update_rev(Key_value);
        pushup(ch[rt][1]);
        pushup(rt);
    }
    
    int Get_sum(int pos,int tot)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        return sum[Key_value];
    }
    
    int Get_maxsum(int pos,int tot)
    {
        splay(get_kth(rt,pos),0);
        splay(get_kth(rt,pos+tot+1),rt);
        return mx[Key_value];
    }
    int main()
    {
        int m,i,j,pos,tot,c;
        char s[10];
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            init();
            while(m--){
                scanf("%s",s);
                if(s[0]=='I'){
                    scanf("%d%d",&pos,&tot);
                    Insert(pos,tot);
                }
                if(s[0]=='D'){
                    scanf("%d%d",&pos,&tot);
                    Delete(pos,tot);
                }
                if(s[0]=='M' && s[2]=='K'){
                    scanf("%d%d%d",&pos,&tot,&c);
                    Make_same(pos,tot,c);
                }
                if(s[0]=='R'){
                    scanf("%d%d",&pos,&tot);
                    Reverse(pos,tot);
                }
                if(s[0]=='G'){
                    scanf("%d%d",&pos,&tot);
                    printf("%d
    ",Get_sum(pos,tot));
                }
                if(s[0]=='M' && s[2]=='X'){
                    printf("%d
    ",Get_maxsum(1,sz[rt]-2) );
                }
            }
        }
        return 0;
    }
    


  • 相关阅读:
    hihoCoder #1176 : 欧拉路·一 (简单)
    228 Summary Ranges 汇总区间
    227 Basic Calculator II 基本计算器II
    226 Invert Binary Tree 翻转二叉树
    225 Implement Stack using Queues 队列实现栈
    224 Basic Calculator 基本计算器
    223 Rectangle Area 矩形面积
    222 Count Complete Tree Nodes 完全二叉树的节点个数
    221 Maximal Square 最大正方形
    220 Contains Duplicate III 存在重复 III
  • 原文地址:https://www.cnblogs.com/herumw/p/9464482.html
Copyright © 2011-2022 走看看