zoukankan      html  css  js  c++  java
  • SP1043 GSS1

    题目描述

    给出了序列A[1],A[2],…,A[N]。 (a[i]≤15007,1≤N≤50000)。查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j];x≤i≤j≤y}。 给定M个查询,程序必须输出这些查询的结果。

    输入输出格式

    输入格式:

    • 输入文件的第一行包含整数N。
    • 在第二行,N个数字跟随。
    • 第三行包含整数M。
    • M行跟在后面,其中第1行包含两个数字xi和yi。

    输出格式:

    您的程序应该输出M查询的结果,每一行一个查询。

    思路:

    我们做这道题首先应该想的,是两个区间如何合并

    很显然,合并后最大子段和,要么是原来左儿子的,要么是原来右儿子的

    还有一种可能是左右两个儿子合并后在中间新生成的

    所以,每个节点维护四个元素

    分别表示他所管辖的区间和,他所管辖的区间中的最大连续子段和

    从左起最大连续子段和(意思是子段的左端点一定是区间的左端点)

    从右起最大连续子段和(意思同上)

    此时我们可以这样转移:

    sum(和)就不用说了

    这一层的从左起最大连续子段和=max(左儿子的从左起最大连续子段和,左儿子的和+右儿子的从左起最大连续子段和)

    这一层的从左起最大连续子段和方法同上

    这一层的最大连续子段和=max(左儿子的最大连续子段和,右儿子的最大连续子段和,(左儿子从右起的最大连续字段和+右儿子从左起的最大连续子段和(也就是合并后生成的中间最大子段)))

    OK,任务完成

    查询同理

    代码:

    //这里我将建树当成更改节点值
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define rii register int i
    #define rij register int j
    #define inf 1073741824
    #define rs 65536
    using namespace std;
    struct nod{
        int lm,rm,maxn,sum;
    }x[6000005];
    int n,q,cz,x1,y1;
    void add(int wz,int l,int r,int val,int bh)
    {
        if(l==r&&l==wz)
        {
            x[bh].maxn=val;
            x[bh].lm=val;
            x[bh].rm=val;
            x[bh].sum=val;
            return;
        }
        int ltt=(l+r)/2;
        if(wz<=ltt)
        {
            add(wz,l,ltt,val,bh*2);
        }
        else
        {
            add(wz,ltt+1,r,val,bh*2+1);
        }
        x[bh].sum=x[bh*2].sum+x[bh*2+1].sum;
        x[bh].lm=max(x[bh*2].lm,x[bh*2].sum+x[bh*2+1].lm);
        x[bh].rm=max(x[bh*2+1].rm,x[bh*2+1].sum+x[bh*2].rm);
        x[bh].maxn=max(x[bh*2].maxn,max(x[bh*2+1].maxn,x[bh*2].rm+x[bh*2+1].lm));
    }
    nod query(int l,int r,int nl,int nr,int bh)
    {
        nod an,bn;
        if(l<nl)
        {
            l=nl;
        }
        if(r>nr)
        {
            r=nr;
        }
        if(nl==l&&nr==r)
        {
            an=x[bh];
            return an;
        }
        int ltt=(nl+nr)/2;
        if(l<=ltt&&r<=ltt)
        {
            return an=query(l,r,nl,ltt,bh*2);
        }
        if(r>ltt&&l>ltt)
        {
            return bn=query(l,r,ltt+1,nr,bh*2+1);
        }
        else
        {
            an=query(l,r,nl,ltt,bh*2);
            bn=query(l,r,ltt+1,nr,bh*2+1);
            an.maxn=max(an.maxn,max(bn.maxn,an.rm+bn.lm));
            an.lm=max(an.lm,an.sum+bn.lm);
            an.rm=max(bn.rm,bn.sum+an.rm);
            an.sum=an.sum+bn.sum;
            return an;
        }
        
    }
    int main()
    {
    //    freopen("brs.in","r",stdin);
    //    freopen("brs.out","w",stdout);
        for(rii=1;i<=150005;i++)
        {
            x[i].lm=-inf;
            x[i].rm=-inf;
            x[i].maxn=-inf;
        }
        scanf("%d",&n);
        for(rii=1;i<=n;i++)
        {
            int ltt;
            scanf("%d",&ltt);
            add(i,1,rs,ltt,1);
        }
        scanf("%d",&q);
        for(rii=1;i<=q;i++)
        {
            scanf("%d%d",&x1,&y1);
            nod ans=query(x1,y1,1,rs,1);
            printf("%d
    ",ans.maxn);
        }
    }
  • 相关阅读:
    xls与csv文件的区别
    青音,经典爱情语录
    win7用户账户自动登录方法汇总
    How to using Procedure found Lead Blocker
    FTS(3) BSD 库函数手册 遍历文件夹(二)
    FTS(3) BSD 库函数手册 遍历文件夹(一)
    DisplayMetrics类 获取手机显示屏的基本信息 包括尺寸、密度、字体缩放等信息
    About App Distribution 关于应用发布
    FTS(3) 遍历文件夹实例
    OpenCV 2.1.0 with Visual Studio 2008
  • 原文地址:https://www.cnblogs.com/ztz11/p/9343366.html
Copyright © 2011-2022 走看看