Remove the Bracket
题目描述:
RSJ has a sequence \(a\) of \(n\) integers \(a_1,a_2,…,a_n\) and \(a_n\) integer \(s\). For each of \(a_2,a_3,…,a_{n−1}\), he chose a pair of non-negative integers \(x_i\) and \(y_i\) such that \(x_i+y_i=a_i\) and \((x_i−s)⋅(y_i−s)≥0\).
Now he is interested in the value
Please help him find the minimum possible value \(F\) he can get by choosing \(x_i\) and \(y_i\) optimally. It can be shown that there is always at least one valid way to choose them.
输入描述:
Each test contains multiple test cases. The first line contains an integer \(t(1≤t≤10^4 )\) — the number of test cases.
The first line of each test case contains two integers \(n, s (3≤n≤2⋅10^5; 0≤s≤2⋅10^5)\).
The second line contains \(n\) integers \(a_1,a_2,…,a_n(0≤a_i≤2⋅10^5)\).
It is guaranteed that the sum of \(n\) does not exceed \(2⋅10^5\).
输出描述:
For each test case, print the minimum possible value of \(F\).
样例:
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, \(2⋅0+0⋅1+0⋅3+0⋅4=0\).
In the second test case, \(5⋅1+2⋅2+2⋅2+1⋅5=18\).
AC代码:
题目中公式
对于\(\forall\)\(i(2 ≤ i ≤ n - 1)\) 提取出
由于\(x_i + y_i = a_i\), 所以\(y_i = a_i - x_i\),带入原式中得
所以原式就变成了关于\(x_i\)的一次函数,那么函数的最值也就是会在\(x_i\)取最值的时候取到
- \(a_i ≤s\)时,可以取最值\(0\)和\(a_i\)
- \(a_i >s\)时,可以取最值\(s\)和\(a_i - s\)
这两种情况都保证满足\((x_i - s) \cdot (y_i - s) ≥ 0\)
这样可以采取DP
采用一个数组\(f[i][j]\),其状态表示为
- 当\(j = 0\)时,\(x_i\)取最小值时的结果
- 当\(j = 1\)时,\(x_i\)取最大值时的结果
而\(f[i][j]\)则有可能是从\(f[i - 1][0]\) 或 \(f[j - 1][1]\) 中转移过来,所以状态计算为
- \(f[i][0] = min(f[i - 1][0] + maxv(y_{i - 1}) \cdot minv(x_i), f[i - 1][1] + minv \cdot minv)\)
- \(f[i][1] = min(f[i - 1][0] + maxv(y_{i - 1}) \cdot maxv(x_i),f[i - 1][1] + minv \cdot maxv)\)
最后结果取\(f[n][0]\)和\(f[n][1]\)的最小值即可(最终结果\(f[n][0]\)和\(f[n][1]\)大小是一样的,但是我不明白为什么)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
LL f[N][2];
LL x[N], y[N];
void solve()
{
int n, s;
cin >> n >> s;
for(int i = 1; i <= n; i ++)
{
int m;
cin >> m;
if(i == 1 || i == n)
{
x[i] = y[i] = m;
}
else if(m <= s)
{
x[i] = 0, y[i] = m;
}
else
{
x[i] = min(s, m - s), y[i] = max(s, m - s);
}
}
f[1][0] = f[1][1] = 0;
for(int i = 2; i <= n; i ++)
{
f[i][0] = min(f[i - 1][0] + y[i - 1] * x[i], f[i - 1][1] + x[i - 1] * x[i]);
f[i][1] = min(f[i - 1][0] + y[i - 1] * y[i], f[i - 1][1] + x[i - 1] * y[i]);
}
cout << f[n][0] << '\n';
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T --)
solve();
return 0;
}