D. Maximum Subarray

D. Maximum Subarray

You are given an array a1,a2,,an, consisting of n integers. You are also given two integers k and x.

You have to perform the following operation exactly once: add x to the elements on exactly k distinct positions, and subtract x from all the others.

For example, if a=[2,1,2,3], k=1, x=2, and we have picked the first element, then after the operation the array a=[4,3,0,1].

Let f(a) be the maximum possible sum of a subarray of a. The subarray of a is a contiguous part of the array a, i. e. the array ai,ai+1,,aj for some 1ijn. An empty subarray should also be considered, it has sum 0.

Let the array a be the array a after applying the aforementioned operation. Apply the operation in such a way that f(a) is the maximum possible, and print the maximum possible value of f(a).

Input

The first line contains a single integer t (1t104) — the number of test cases.

The first line of each test case contains three integers n, k and x (1n2105; 0kmin(20,n); 109x109).

The second line contains n integers a1,a2,,an (109ai109).

The sum of n over all test cases doesn't exceed 2105.

Output

For each test case, print one integer — the maximum possible value of f(a).

Example

input

复制代码
4
4 1 2
2 -1 2 3
2 2 3
-1 2
3 0 5
3 2 4
6 2 -8
4 -1 9 -3 7 -8
复制代码

output

5
7
0
44

 

解题思路

  一开始还真没想到用dp。

  定义状态f(i,j)表示在前i个数中,所有选择了第i个数且选择了j个不同位置加上x的连续子段和方案的集合,属性就是所有方案中连续子段和的最大值。根据第i个数所在的连续子段所包含的数,即只有第i个数或还有第i1个数所构成的连续子段,以及第i个数是加上x还是减去x来划分方案。因此状态转移方程就是

f(i,j)={max{aix, f(i1,j)+aix},(j<i)(1)max{ai+x, f(i1,j1)+ai+x},(j>0)(2)

  其中(1)式的条件意味着,如果有j=i那么1i中的数都必须要加上x,因此第i个数必须加上x,而不能减去x

  如果j同时满足两个条件,那么f(i,j)就是(1)式和(2)式的最大值。

  其中对于每个ij都对应着一个合法的范围。首先很明显j要同时满足jijk,还要有j+nik即后面的ni个数加上j至少要有k个,否则如果后面ni个数全加上x再加上前面的j个还不足k个,就不满足题目要求了。因此j[max{0,kn+1}, min{i,k}]

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10, M = 30;
 7 
 8 int a[N];
 9 LL f[N][M];
10 
11 void solve() {
12     int n, m, k;
13     scanf("%d %d %d", &n, &m, &k);
14     for (int i = 1; i <= n; i++) {
15         scanf("%d", a + i);
16     }
17     for (int i = 0; i <= n; i++) {
18         for (int j = 0; j <= m; j++) {
19             f[i][j] = -0x3f3f3f3f3f3f3f3f;
20         }
21     }
22     f[0][0] = 0;
23     LL ret = 0;
24     for (int i = 1; i <= n; i++) {
25         for (int j = max(0, m - n + i); j <= m && j <= i; j++) {
26             if (j < i) f[i][j] = max(0ll, f[i - 1][j]) + a[i] - k;
27             if (j) f[i][j] = max(f[i][j], max(0ll, f[i - 1][j - 1]) + a[i] + k);
28             ret = max(ret, f[i][j]);
29         }
30     }
31     printf("%lld\n", ret);
32 }
33 
34 int main() {
35     int t;
36     scanf("%d", &t);
37     while (t--) {
38         solve();
39     }
40     
41     return 0;
42 }
复制代码

 

参考资料

  Educational Codeforces Round 144 Editorial:https://codeforces.com/blog/entry/113408

posted @   onlyblues  阅读(136)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示