C. Remove the Bracket
C. Remove the Bracket
RSJ has a sequence of integers and an integer . For each of , he chose a pair of non-negative integers and such that and .
Now he is interested in the value
Please help him find the minimum possible value he can get by choosing and optimally. It can be shown that there is always at least one valid way to choose them.
Input
Each test contains multiple test cases. The first line contains an integer () — the number of test cases.
The first line of each test case contains two integers , (; ).
The second line contains integers ().
It is guaranteed that the sum of does not exceed .
Output
For each test case, print the minimum possible value of .
Example
input
10 5 0 2 0 1 3 4 5 1 5 3 4 3 5 7 2 7 6 5 4 3 2 1 5 1 1 2 3 4 5 5 2 1 2 3 4 5 4 0 0 1 1 1 5 5 4 3 5 6 4 4 1 0 2 1 0 3 99999 200000 200000 200000 6 8139 7976 129785 12984 78561 173685 15480
output
0 18 32 11 14 0 16 0 40000000000 2700826806
Note
In the first test case, .
In the second test case, .
解题思路
这题一看这么多变量不好下手,实际上要想到把其他变量固定而只考虑某个变量的取值。具体来说就是,假设除和外其他的变量都是固定的值,再来求的最小值。
这个就好求多了,其中和能够影响到的项只有,而,因此就有。由于只有是变量,因此可以发现这个一元线性函数,很明显要使得取到最小值,那么的取值一定是定义域的其中一个端点(此时也是其定义域的一个端点)。
的定义域就与和有关系了:
- 如果,那么,因此要么是,要么是。
- 如果,同理要么是,要么是。
因此可以发现,当其他变量固定时,要使得取到最小值那么和应该取定义域的两个端点,有两种组合。剩下的就是枚举种情况取最小值就可以了,因此可以考虑用状态机dp。
定义状态和,其中这里的和表示和取值的两种组合情况(第种情况就是对第种的和两两交换一下就可以了)。因此就表示前项和且是第种组合的最小值,同理就表示前项和且是第种组合的最小值。这里的前项和是指。状态划分就根据第项是哪种组合来转移就可以了,具体看状态转移方程:
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 LL x[N], y[N]; 9 LL f[N][2]; 10 11 void solve() { 12 int n, m; 13 scanf("%d %d", &n, &m); 14 for (int i = 1; i <= n; i++) { 15 LL v; 16 scanf("%lld", &v); 17 if (i == 1 || i == n) x[i] = y[i] = v; 18 else if (v <= m) x[i] = 0, y[i] = v; 19 else x[i] = v - m, y[i] = m; 20 } 21 for (int i = 2; i <= n; i++) { 22 f[i][0] = min(f[i - 1][0] + y[i - 1] * x[i], f[i - 1][1] + x[i - 1] * x[i]); 23 f[i][1] = min(f[i - 1][0] + y[i - 1] * y[i], f[i - 1][1] + x[i - 1] * y[i]); 24 } 25 printf("%lld\n", f[n][0]); 26 } 27 28 int main() { 29 int t; 30 scanf("%d", &t); 31 while (t--) { 32 solve(); 33 } 34 35 return 0; 36 }
参考资料
TypeDB Forces 2023 (Div. 1 + Div. 2, Rated, Prizes!) Editorial:https://codeforces.com/blog/entry/112009
TypeDB Forces 2023 (Div. 1 + Div. 2, Rated, Prizes!)(持续更新):https://www.cnblogs.com/cjjsb/p/17077371.html
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17079585.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效