题目:CF1155D.
题目大意:给定一个长度为
n
n
n的序列
a
a
a和一个数字
x
x
x,现在可以给任意一段(可以为空)乘
x
x
x,现在要求这样操作得到的最大子段和的最大值.
1
≤
n
≤
3
∗
1
0
5
1\leq n\leq 3*10^5
1≤n≤3∗105.
考场根本没想到DP,一直在想贪心…
我们设 d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示以 a [ i ] a[i] a[i]为结尾不考虑乘 x x x时的最大值, d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示以 a [ i ] ∗ x a[i]*x a[i]∗x为结尾的最大值, d p [ i ] [ 2 ] dp[i][2] dp[i][2]表示以 a [ i ] a[i] a[i]为结尾且考虑乘 x x x时的最大值.
那么容易得到方程:
d
p
[
i
]
[
0
]
=
max
(
d
p
[
i
−
1
]
[
0
]
,
a
[
i
]
)
d
p
[
i
]
[
1
]
=
max
(
max
(
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
)
+
a
[
i
]
∗
x
,
a
[
i
]
∗
x
)
d
p
[
i
]
[
2
]
=
max
(
max
(
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
,
d
p
[
i
−
1
]
[
2
]
)
+
a
[
i
]
,
a
[
i
]
)
dp[i][0]=\max (dp[i-1][0],a[i])\\ dp[i][1]=\max (\max(dp[i-1][0],dp[i-1][1])+a[i]*x,a[i]*x)\\ dp[i][2]=\max (\max(dp[i-1][0],dp[i-1][1],dp[i-1][2])+a[i],a[i])
dp[i][0]=max(dp[i−1][0],a[i])dp[i][1]=max(max(dp[i−1][0],dp[i−1][1])+a[i]∗x,a[i]∗x)dp[i][2]=max(max(dp[i−1][0],dp[i−1][1],dp[i−1][2])+a[i],a[i])
时间复杂度 O ( n ) O(n) O(n).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=300000;
int n;
LL a[N+9],x,dp[N+9][3],mx;
Abigail into(){
scanf("%d%I64d",&n,&x);
for (int i=1;i<=n;++i)
scanf("%I64d",&a[i]);
}
Abigail work(){
for (int i=1;i<=n;++i){
dp[i][0]=max(dp[i-1][0]+a[i],a[i]);
dp[i][1]=max(max(dp[i-1][0],dp[i-1][1])+a[i]*x,a[i]*x);
dp[i][2]=max(max(dp[i-1][0],max(dp[i-1][1],dp[i-1][2]))+a[i],a[i]);
mx=max(max(mx,dp[i][0]),max(dp[i][1],dp[i][2]));
}
}
Abigail outo(){
printf("%I64d\n",mx);
}
int main(){
into();
work();
outo();
return 0;
}