最大子段和DP前缀和C. Increase Subarray Sums
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子段和DP前缀和C. Increase Subarray Sums相关的知识,希望对你有一定的参考价值。
题目链接:
https://codeforces.com/contest/1644/problem/C
f ( k ) f(k) f(k)表示对一个数组中不同的k个元素做加
x
操作,最后的最大字段和。
求 f ( 0 ) , f ( 1 ) , . . . , f ( n ) f(0),f(1),...,f(n) f(0),f(1),...,f(n)
对数组a
做前缀和
状态表示:
f
[
i
−
j
+
1
]
f[i-j+1]
f[i−j+1]:子段长度为i - j + 1
的最大子段和
状态转移:
f
[
i
−
j
+
1
]
=
m
a
x
(
f
[
i
−
j
+
1
]
,
s
[
i
]
−
s
[
j
−
1
]
)
f[i-j+1] = max(f[i-j+1],s[i]-s[j -1])
f[i−j+1]=max(f[i−j+1],s[i]−s[j−1])
这个用动态规划求解最大子段和,复杂度 O ( N 2 ) O(N^2) O(N2)
f[0] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
f[i - j + 1] = max(f[i - j + 1], s[i] - s[j - 1]);
因为还有增强的个数,所以最后统计需要加上增强的个数。
假设增强了j
次,统计最大子段的长度为i
,那么最多增强
m
i
n
(
i
,
j
)
min(i,j)
min(i,j)次,在所有的情况中取最佳即可
#include<bits/stdc++.h>
using namespace std;
int main()
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t--)
int n, x;
cin >> n >> x;
vector<int> a(n + 1), s(n + 1, 0);
for(int i = 1; i <= n; i++)
cin >> a[i];
s[i] = s[i - 1] + a[i];
vector<int> f(n + 1, -1e9);
f[0] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
f[i - j + 1] = max(f[i - j + 1], s[i] - s[j - 1]);
for(int i = 0; i <= n; i++)
int res = 0;
for(int j = 0; j <= n; j++)
res = max(res, f[j] + min(i, j) * x);
cout << res << " \\n"[i == n];
return 0;
以上是关于最大子段和DP前缀和C. Increase Subarray Sums的主要内容,如果未能解决你的问题,请参考以下文章
算法初探系列14——线性DP进阶之最大子段和与最长上升子序列
51nod 1052 最大M子段和 & 1053 最大M子段和 V2