环线
小A喜欢乘坐地铁!
地铁环线一共有n个站点(n<3*10^5)。 每个站点有一个快乐值A[i]。每当经过该站台,小A就能得到该站台的快乐值。注意,快乐值可能为负数(|a[i]|<=10^9)。
注意:第i站的下一站为第i+1站,但第n站的下一站为第1站。
每个站点小A最多经过一次。求他得到的最大快乐值之和。
样例1
4-1 2 3 0
5
(解释:第2站-第3站)
样例2
5-3 4 -5 1 3
5
(解释:只有第3站不坐)
思路
ONE 暴力
n^2的复杂度。
TWO 区间和
通过观察可以发现,从一个点L到点R(L<R)分两种情况:
路径1:L->1->R
路径2:l->R
当然,在这个基础上,我们能得到:
第一种的数值之和=全程的数值之和-第二种的数值之和。
因此,这道题,可以转化成区间和问题!
但是时间复杂度不会有丝毫优化。
……
TWO pro
通过TWO不难发现,对于一个路径2,若它有固定的R,那么让其1->L的和最小,就能做到数值之和最大。
sum=前缀和[R]-min(前缀和1-R)
同样的原理,要使一个有固定R的路径1和最大,那就要让1->L的和最大。
sum2=前缀和[n]-[前缀和[R]-max(前缀和[1-R])]
然后再把sum与sum2录入答案就可以了。
O(n)AC.
代码
/*CPP*/
#include <bits/stdc++.h>
using namespace std;
int a[300005],b[300005];
int maxn[300005],minx[300005];//maxn[i]=max(b[1],b[2],b[3]...b[i]),minx同理
long long n,ans;
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];b[i]=b[i-1]+a[i];maxn[i]=max(maxn[i-1],b[i]);//注意,是B i而不是A i minx[i]=min(minx[i-1],b[i]);}for(int i=1;i<=n;i++){long long sum,sum2; sum=b[i]-minx[i];//L-R sum2=b[n]-b[i]+maxn[i];//L-1-R ans=max(ans,max(sum,sum2));}cout<<ans;return 0;
}