spoj 1043. Can you answer these queries I (线段树)

题目链接:http://www.spoj.pl/problems/GSS1/

 

题意:给出n个数,询问某一区间中,最大的连续子段和。

思路:用线段树维护3个值:maxv[rt]:区间最大连续子段和,pre[rt]:区间最大前缀和,suff[rt]:区间最大后缀和,就是合并时改一改就好了,其实很简单的。

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=50000+10;
int sum[maxn],maxv[maxn<<2],pre[maxn<<2],suff[maxn<<2];
inline void PushUp(int l,int r,int rt)
{
    int m=(l+r)>>1;
    int ls=rt<<1,rs=rt<<1|1;
    maxv[rt]=max(maxv[ls],maxv[rs]);
    maxv[rt]=max(maxv[rt],suff[ls]+pre[rs]);
    pre[rt]=max(sum[m]-sum[l-1]+pre[rs],pre[ls]);
    suff[rt]=max(sum[r]-sum[m]+suff[ls],suff[rs]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        maxv[rt]=pre[rt]=suff[rt]=sum[l]-sum[l-1];
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    PushUp(l,r,rt);
}
int Query(int L,int R,int l,int r,int rt,int &ps,int &lsum,int &rsum)
{
    if(l>=L&&r<=R)
    {
        lsum=pre[rt];rsum=suff[rt];
        ps=sum[r]-sum[l-1];
        return maxv[rt];
    }
    int m=(l+r)>>1;
    int ls=rt<<1,rs=rt<<1|1;
    if(R<=m)
     return Query(L,R,l,m,ls,ps,lsum,rsum);
    else if(L>m)
     return Query(L,R,m+1,r,rs,ps,lsum,rsum);
    else
    {
        int ltmp1,rtmp1,ltmp2,rtmp2,s,ps1,ps2;
        int s1=Query(L,R,l,m,ls,ps1,ltmp1,rtmp1);
        int s2=Query(L,R,m+1,r,rs,ps2,ltmp2,rtmp2);
        s=max(s1,s2);
        s=max(s,rtmp1+ltmp2);
        lsum=max(ltmp1,ps1+ltmp2);
        rsum=max(rtmp2,ps2+rtmp1);
        ps=ps1+ps2;
        return s;
    }
}
int main()
{
    //freopen("a.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,q;
    while(~scanf("%d",&n))
    {
        sum[0]=0;
        int a;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a);
            sum[i]=sum[i-1]+a;
        }
        build(1,n,1);
        scanf("%d",&q);
        int l,r,tm1,tm2,tm3;
        while(q--)
        {
            scanf("%d%d",&l,&r);
            printf("%d\n",Query(l,r,1,n,1,tm1,tm2,tm3));
        }
    }
    return 0;
}


 

你可能感兴趣的:(数据结构,线段树)