2479 Maximum sum
問題概要
数列A={a1,a2,...,an}に対して
d(A)=max{Σ[i=s1,t1]a[i] + Σ[i=s2,t2]a[i]|1≦s1≦t1<s2≦t2≦n}
で定める。d(A)を求めよ。
n≦50000以下である。
解法
数列の区間[0,i]の中の連続する部分数列の和の最大値は、全てのiに対してまとめてO(n)で以下のように求められる。
dp[i]:i番目までの連続する部分数列の和の最大値
dp2[i]:i番目までの連続する部分数列のうち、a[i]を含むようなものの和の最大値
とすれば、
dp2[i]=max(a[i],dp2[i-1]+a[i])
dp[i]=max(dp[i-1],dp2[i])
これを両端からやり、表を作っておいた上で、二つの数列の区切りをn-1通り試せばよい。
ソースコード
int T,n,a[50000]; int h[50000],t[50000],c[50000]; void func(int *d){ d[0]=c[0]=a[0]; for(int i=1;i<n;i++){ c[i]=max(c[i-1],0)+a[i]; d[i]=max(d[i-1],c[i]); } } int main(){ scanf("%d",&T); rep(U,T){ scanf("%d",&n); rep(i,n)scanf("%d",a+i); func(h); reverse(a,a+n); func(t); int ans=-(1<<30); rep(i,n-1)ans=max(ans,h[i]+t[n-2-i]); printf("%d\n",ans); } return 0; }