题面
分析
不说怎么暴力,因为暴力的难度与得分成正比
正解动归
设
l
[
i
]
l[i]
l[i]:区间[1,i]的最大连续和(最大子区间和)
r
[
i
]
r[i]
r[i]:区间[i,n]的最大连续和
(1<=i<=n)
那么易得
S
=
m
a
x
(
l
[
i
]
+
r
[
i
+
1
]
)
S=max(l[i]+r[i+1])
S=max(l[i]+r[i+1])
而
l
[
i
]
l[i]
l[i]和
r
[
i
]
r[i]
r[i]的维护可以再次写出方程
l
[
i
]
=
m
a
x
(
l
[
i
−
1
]
,
s
u
m
[
i
]
−
m
i
n
(
s
u
m
[
j
]
)
)
,
1
<
=
i
<
=
n
,
j
<
i
l[i]=max(l[i-1],sum[i]-min(sum[j])),1<=i<=n,j<i
l[i]=max(l[i−1],sum[i]−min(sum[j])),1<=i<=n,j<i
l[i-1]意为区间[1,i]的最大连续和不以i结尾,sum[i]-min(sum[j])意为区间[1,i]的最大连续和以i结尾
r [ i ] = m a x ( r [ i + 1 ] , s u m [ i ] − m i n ( s u m [ j ] ) ) , 1 < = i < = n , i < j < = n r[i]=max(r[i+1],sum[i]-min(sum[j])),1<=i<=n,i<j<=n r[i]=max(r[i+1],sum[i]−min(sum[j])),1<=i<=n,i<j<=n
l[i-1]意为区间[i,n]的最大连续和不以i开头,sum[i]-min(sum[j])意为区间[1,i]的最大连续和以i开头
sum[i]指1到i的前缀和
sum[i]-min(sum[j])其实就是区间和
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;i++)
#define anti_loop(i,start,end) for(int i=start;i>=end;i--)
#define clean(arry,num); memset(arry,num,sizeof(arry));
#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)
#define ll long long
int n;
const int maxn=100000+100;
int a[maxn];
ll l[maxn];
ll r[maxn];
inline int read()
{
bool neg=false;int res=0;char r=getchar();
while(r>'9'||r<'0'){if(r=='-')neg=true;r=getchar();}
while(r>='0'&&r<='9'){res=res*10+r-'0';r=getchar();}
return (neg)?-res:res;
}
int main()
{
//freopen("datain2.txt","r",stdin);
n=read();clean(a,0);clean(l,0);clean(r,0);
ll sum=0,minsum=0;r[n+1]=l[0]=-0x7f7f7f;
//注意要处理好r[n+1]=l[0],因为在计算r[n],l[1]时要用到其值(其实是不想特判啦)
loop(i,1,n)
{
a[i]=read();
sum+=a[i];//
l[i]=(i==1)?a[i]:max(l[i-1],sum-minsum);
minsum=min(minsum,sum);
//也要注意维护min(sum[j]),j<i,不可取等,故minsum要在计算出第一个数后才更新
}
sum=0;minsum=0;
anti_loop(i,n,1)
{
sum+=a[i];
r[i]=(i==n)?a[i]:max(r[i+1],sum-minsum);
minsum=min(minsum,sum);
}
//ll maxx=0;不要这样写!!有负数!!
ll maxx=-0x9f9f9f;
loop(i,1,n)maxx=max(maxx,l[i]+r[i+1]);
printf("%lld",maxx);
return 0;
}
学到的东西
1.类题:最大连续子序列和
其实本题就是图中问题的一个扩展,我们如果用图中所讲的方法,从左向右求一次dp[i](意义同图),再从右向左求一次dp2[i](dp2[i]指以a[i]作为起点的连续序列最大和),然后枚举i求max,其实也是可以得到本题的解的,只是可能要麻烦一些罢了
方程:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
−
1
]
+
A
[
i
]
,
A
[
i
]
)
dp[i]=max(dp[i-1]+A[i],A[i])
dp[i]=max(dp[i−1]+A[i],A[i])
d
p
2
[
i
]
=
m
a
x
(
d
p
[
i
+
1
]
+
A
[
i
]
,
A
[
i
]
)
dp2[i]=max(dp[i+1]+A[i],A[i])
dp2[i]=max(dp[i+1]+A[i],A[i])
S
=
m
a
x
(
d
p
[
i
]
+
d
p
2
[
i
]
)
S=max(dp[i]+dp2[i])
S=max(dp[i]+dp2[i])
这样应该可以的