D. Maximum Subarray
D. Maximum Subarray
You are given an array , consisting of integers. You are also given two integers and .
You have to perform the following operation exactly once: add to the elements on exactly distinct positions, and subtract from all the others.
For example, if , , , and we have picked the first element, then after the operation the array .
Let be the maximum possible sum of a subarray of . The subarray of is a contiguous part of the array , i. e. the array for some . An empty subarray should also be considered, it has sum .
Let the array be the array after applying the aforementioned operation. Apply the operation in such a way that is the maximum possible, and print the maximum possible value of .
Input
The first line contains a single integer () — the number of test cases.
The first line of each test case contains three integers , and (; ; ).
The second line contains integers ().
The sum of over all test cases doesn't exceed .
Output
For each test case, print one integer — the maximum possible value of .
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。
定义状态表示在前个数中,所有选择了第个数且选择了个不同位置加上的连续子段和方案的集合,属性就是所有方案中连续子段和的最大值。根据第个数所在的连续子段所包含的数,即只有第个数或还有第个数所构成的连续子段,以及第个数是加上还是减去来划分方案。因此状态转移方程就是
其中式的条件意味着,如果有那么中的数都必须要加上,因此第个数必须加上,而不能减去。
如果同时满足两个条件,那么就是式和式的最大值。
其中对于每个,都对应着一个合法的范围。首先很明显要同时满足且,还要有即后面的个数加上至少要有个,否则如果后面个数全加上再加上前面的个还不足个,就不满足题目要求了。因此。
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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17177714.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效