• 3981 动态最大子段和


    题目描述 Description

    题目还是简单一点好... 

    有n个数,a[1]到a[n]。

    接下来q次查询,每次动态指定两个数l,r,求a[l]到a[r]的最大子段和。

    子段的意思是连续非空区间。

    输入描述 Input Description

    第一行一个数n。

    第二行n个数a[1]~a[n]。

    第三行一个数q。

    以下q行每行两个数l和r。

    输出描述 Output Description

    q行,每行一个数,表示a[l]到a[r]的最大子段和。

    样例输入 Sample Input

    7
    2 3 -233 233 -23 -2 233
    4
    1 7
    5 6
    2 5
    2 3

    样例输出 Sample Output

    441
    -2
    233
    3

    数据范围及提示 Data Size & Hint

    对于50%的数据,q*n<=10000000。

    对于100%的数据,1<=n<=200000,1<=q<=200000。

    a[1]~a[n]在int范围内,但是答案可能超出int范围。

    数据保证1<=l<=r<=n。

    空间128M,时间1s。

    我不会告诉你数据里有样例

     
     
    //题意:询问一段区间的最大子序列的值。
    //就是GSS1多开点空间然后开longlong 
    
    //做法:维护四个值:包含当前区间左端点的最大子区间LM,包含当前区间右端点的最大子区间RM、当前区间的最大子区间M, 当前区间的区间和S 
    //tree[root].maxn=max(tree[root<<1].maxn,max(tree[root<<1|1].maxn,tree[root<<1].rmaxn+tree[root<<1|1].lmaxn));
    //    tree[root].lmaxn=max(tree[root<<1].lmaxn,tree[root<<1].sum+tree[root<<1|1].lmaxn);
    //    tree[root].rmaxn=max(tree[root<<1|1].rmaxn,tree[root<<1|1].sum+tree[root<<1].rmaxn);
    //    tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N=2e5+5;
    
    int n,m,l,r;
    long long L,R,M,S;
    struct Tree
    {
        int l,r,mid;
        long long sum,lmaxn,rmaxn,maxn;
    }tree[N<<2];
    
    inline long long read()
    {
        char c=getchar();long long num=0,f=1;
        for(;!isdigit(c);c=getchar())
            f=c=='-'?-1:f;
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num*f;
    }
    
    inline void pushup(int root)
    {
        tree[root].maxn=max(tree[root<<1].maxn,max(tree[root<<1|1].maxn,tree[root<<1].rmaxn+tree[root<<1|1].lmaxn));
        tree[root].lmaxn=max(tree[root<<1].lmaxn,tree[root<<1].sum+tree[root<<1|1].lmaxn);
        tree[root].rmaxn=max(tree[root<<1|1].rmaxn,tree[root<<1|1].sum+tree[root<<1].rmaxn);
        tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
    }
    
    void build(int root,int l,int r)
    {
        tree[root].l=l,tree[root].r=r,tree[root].mid=l+r>>1;
        if(l==r)
        {
            tree[root].sum=tree[root].maxn=tree[root].rmaxn=tree[root].lmaxn=read();
            return;
        }
        build(root<<1,l,tree[root].mid);
        build(root<<1|1,tree[root].mid+1,r);
        pushup(root);
    }
    
    void query(int root,int l,int r,long long &L,long long &R,long long &M,long long &S)
    {
        if(l<=tree[root].l&&tree[root].r<=r)
        {
            L=tree[root].lmaxn,
            R=tree[root].rmaxn,
            M=tree[root].maxn,
            S=tree[root].sum;
            return;
        }
        if(tree[root].mid>=r)
        {
            query(root<<1,l,r,L,R,M,S);
        }
        else if(tree[root].mid<l)
        {
            query(root<<1|1,l,r,L,R,M,S);
        }
        else
        {
            long long lL=0,lR=0,lM=0,lS=0,rL=0,rR=0,rM=0,rS=0;
            query(root<<1,l,tree[root].mid,lL,lR,lM,lS);
            query(root<<1|1,tree[root].mid+1,r,rL,rR,rM,rS);
            L=max(lL,lS+rL);
            R=max(rR,rS+lR);
            M=max(lR+rL,max(lM,rM));
            S=lS+rS;
        }
    }
    
    int main()
    {
        n=read();
        build(1,1,n);
        m=read();
        for(int i=1;i<=m;++i)
        {
            l=read(),r=read();
            query(1,l,r,L,R,M,S);
            printf("%lld
    ",M);
        }
        return 0;
    }
  • 相关阅读:
    我是如何去了解jquery的(六),案例之幻灯片轮换
    近两年学习博客案例目录整理
    我是如何去了解jquery的(三),事件之点击事件,光棍节特献
    滚动鼠标放大缩小图片效果,兼容火狐
    自己动手制作jquery插件之自动添加删除行(下)
    JY案例一:瀑布流布局页面
    我是如何去了解jquery的(一),从查询开始
    自己动手制作jquery插件之自动添加删除行(上)
    我是如何去了解jquery的(二),复杂选择符
    我是如何去了解jquery的(七),案例之不间断滚动
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8747527.html
Copyright © 2020-2023  润新知