【HDOJ】1003 Max Sum

【题目】http://acm.hdu.edu.cn/showproblem.php?pid=1003

【报告】

    既然是子区间加和问题,可以用减法来处理。比如求[5..10]的和,可以直接用[1..10]的和剪掉[1..4]的和。这个很常用,也很有用;

    不过暴力首尾肯定是要TLE的,那么来分析一下题目。

    先求出[1..n]的和,记为s[n],那假设我们需要的Max Sum就是[A..B]段。显然,s[B]是第A位之后S最大的一项。所以接下来的问题是,对于一个A,求出B。

    我们可以用一个指示数组P[i],来指示第i位之后的最大项的位置。然后枚举i,求出差值的最大值,就是最后的答案了。

    这个指示数组的构造就不用说了吧,很简单的……

    至此,完美AC。

【程序】

// TASK: 1003 Max Sum
#include <cstdlib>
#include <iostream>
#include <cstdio>
#define N 100000
using namespace std;
long s[N+1],p[N+1];
long n;
long S,B,E;
int main(int argc, char *argv[])
{
    long t;
    cin >> t;
    bool first=true;
    for (long dex=1;dex<=t;dex++)
    {
        if (!first) cout << endl;
        first=false;
        cin >> n;
        memset(s,0,sizeof(s));
        B=E=0;
        S=-2147483647;
        for (long i=1;i<=n;i++)
        {
            cin >> s[i];
            s[i]+=s[i-1];
            p[i]=i+1;
        }
        p[n]=n;
        p[0]=1;
        for (long i=n-1;i>=0;i--)
            if (s[p[i]]<s[p[i+1]])
               p[i]=p[i+1];
        for (long i=0;i<n;i++)
            if (S<s[p[i]]-s[i])
            {
               S=s[p[i]]-s[i];
               B=i+1;
               E=p[i];
            }
        cout << "Case " << dex << ":" << endl;

posted @ 2012-08-06 11:49  为美好世界献上珂学  阅读(139)  评论(0)    收藏  举报