【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;

浙公网安备 33010602011771号