zoukankan      html  css  js  c++  java
  • SP4487 GSS6

    题目大意

    给出一个由N个整数组成的序列A,你需要应用M个操作:

    • I p x p  处插入插入一个元素 x
    • D p 删除 p 处的一个元素
    • R p x 修改 p 处元素的值为 x
    • Q l r 查询一个区间[l,r]的最大子段和

    输入格式

    第一行一个数N,表示序列的长度

    第二行N个数,表示初始序列A

    第三行一个数M,表示操作的次数

    接下来的M行,每行一个操作,格式见题目描述

    输出格式

    输出若干行,每行一个整数,表示查询区间的最大子段和

    感谢@Anoxiacxy 提供的翻译

    题目描述

    Given a sequence A of N (N <= 100000) integers, you have to apply Q (Q <= 100000) operations:

    Insert, delete, replace an element, find the maximum contiguous(non empty) sum in a given interval.

    输入输出格式

    输入格式:

    The first line of the input contains an integer N.
    The following line contains N integers, representing the starting
    sequence A1..AN, (|Ai| <= 10000).

    The third line contains an integer Q. The next Q lines contains the operations in following form:

    I x y: insert element y at position x (between x - 1 and x).
    D x : delete the element at position x.
    R x y: replace element at position x with y.
    Q x y: print max{Ai + Ai+1 + .. + Aj | x <= i <= j <= y}.

    All given positions are valid, and given values are between -10000 and +10000.

    The sequence will never be empty.

    输出格式:

    For each "Q" operation, print an integer(one per line) as described above.

    输入输出样例

    输入样例#1: 
    5
    3 -4 3 -1 6
    10
    I 6 2
    Q 3 5
    R 5 -4
    Q 3 5
    D 2
    Q 1 5
    I 2 -10
    Q 1 6
    R 2 -1
    Q 1 6
    
    输出样例#1: 
    8
    3
    6
    3
    5
    

    Solution:

      某天下午和机房巨佬们比赛做这题谁最快AC,巨恶心。

      题意毫无思维难度,写一个平衡树就好了,关键是信息的维护情况贼多,在更新子树信息时要把所有的情况都考虑到,然后就比较码农了。

    代码:

    /*Code by 520 -- 10.18*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    using namespace std;
    const int N=300005;
    int n,m,root,ch[N][2],rnd[N],date[N],cnt,siz[N];
    int lf[N],rf[N],maxn[N],sum[N];
    
    int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-') x=getchar();
        if(x=='-') x=getchar(),f=1;
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return f?-a:a;
    }
    
    il int newnode(int v){
        ++cnt;
        siz[cnt]=1,maxn[cnt]=sum[cnt]=date[cnt]=v,rnd[cnt]=rand(),lf[cnt]=rf[cnt]=max(date[cnt],0);
        return cnt;
    }
    
    il void up(int rt){
        siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1;
        sum[rt]=date[rt]+sum[ch[rt][0]]+sum[ch[rt][1]];
        if(ch[rt][0]&&ch[rt][1]){
            lf[rt]=max(lf[ch[rt][0]],date[rt]+sum[ch[rt][0]]+lf[ch[rt][1]]);
            rf[rt]=max(rf[ch[rt][1]],date[rt]+sum[ch[rt][1]]+rf[ch[rt][0]]);
            maxn[rt]=max(lf[ch[rt][1]]+date[rt]+rf[ch[rt][0]],max(maxn[ch[rt][0]],maxn[ch[rt][1]]));
        }
        else if(ch[rt][0]) lf[rt]=max(max(0,lf[ch[rt][0]]),sum[ch[rt][0]]+date[rt]),rf[rt]=max(0,date[rt]+rf[ch[rt][0]]),maxn[rt]=max(maxn[ch[rt][0]],rf[ch[rt][0]]+date[rt]);
        else if(ch[rt][1]) rf[rt]=max(max(0,rf[ch[rt][1]]),date[rt]+sum[ch[rt][1]]),lf[rt]=max(0,date[rt]+lf[ch[rt][1]]),maxn[rt]=max(maxn[ch[rt][1]],date[rt]+lf[ch[rt][1]]);
        else maxn[rt]=date[rt],lf[rt]=rf[rt]=max(date[rt],0);
    
    }
    
    int merge(int x,int y){
        if(!x||!y) return x+y;
        if(rnd[x]<rnd[y]) {ch[x][1]=merge(ch[x][1],y),up(x);return x;}
        else {ch[y][0]=merge(x,ch[y][0]),up(y);return y;}
    }
    
    void split(int rt,int v,int &x,int &y){
        if(!rt) {x=y=0;return;}
        if(siz[ch[rt][0]]>=v) y=rt,split(ch[rt][0],v,x,ch[y][0]),up(y);
        else x=rt,split(ch[rt][1],v-siz[ch[rt][0]]-1,ch[x][1],y),up(x);
    }
    
    il void ins(int k,int v){
        int x,y; split(root,k-1,x,y);
        root=merge(merge(x,newnode(v)),y);
    }
    
    il void del(int k){
        int x,y,z; split(root,k-1,x,y),split(y,1,y,z);
        root=merge(x,z);
    }
    
    il void change(int k,int v){
        int x,y,z; split(root,k-1,x,y),split(y,1,y,z);
        root=merge(merge(x,newnode(v)),z);
    }
    
    il int query(int l,int r){
        int x,y,z,ans; split(root,r,x,y),split(x,l-1,x,z);
        ans=maxn[z];
        root=merge(merge(x,z),y);
        return ans;
    }
    
    int main(){
        n=gi(); char opt[2];int x,y;
        For(i,1,n) ins(i,gi());
        m=gi();
        while(m--){
            scanf("%s",opt),x=gi();
            if(opt[0]=='I') y=gi(),ins(x,y);
            else if(opt[0]=='D') del(x);
            else if(opt[0]=='R') y=gi(),change(x,y);
            else y=gi(),printf("%d
    ",query(x,y));
        }
        return 0;
    }
  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/five20/p/9862116.html
Copyright © 2011-2022 走看看