原题:
D. Insert a Progression
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a sequence of n
integers
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an. You are also given x integers 1,2,…,x.
You are asked to insert each of the extra integers into the sequence a. Each integer can be inserted at the beginning of the sequence, at the end of the sequence, or between any elements of the sequence.
The score of the resulting sequence
a
′
a^′
a′ is the sum of absolute differences of adjacent elements in it.
∑
i
=
1
n
+
z
−
1
∣
a
i
′
−
a
i
+
1
′
∣
\sum_{i=1}^{n+z-1} |a_i'-a_{i+1}'|
i=1∑n+z−1∣ai′−ai+1′∣
What is the smallest possible score of the resulting sequence
a
′
a'
a′?
Input
The first line contains a single integer t (1≤t≤ 1 0 4 10^4 104) — the number of testcases.
The first line of each testcase contains two integers n and x (1≤n,x≤ 2 ⋅ 1 0 5 2⋅10^5 2⋅105) — the length of the sequence and the number of extra integers.
The second line of each testcase contains n
integers a1,a2,…,an (1≤ai≤
2
⋅
1
0
5
2⋅10^5
2⋅105).
The sum of n over all testcases doesn’t exceed
2
⋅
1
0
5
2⋅10^5
2⋅105
.
Output
For each testcase, print a single integer — the smallest sum of absolute differences of adjacent elements of the sequence after you insert the extra integers into it.
Example
Input
4
1 5
10
3 8
7 2 10
10 2
6 1 5 7 3 3 9 10 10 1
4 10
1 3 1 2
Output
Copy
9
15
31
13
Note
Here are the sequences with the smallest scores for the example. The underlined elements are the extra integers. Note that there exist other sequences with this smallest score.
1 ,2 ,3 ,4 ,5 ,10
7 ,7,6 ,4 ,2,2 ,1 ,3 ,5 ,8 ,10
6,1 ,1,2 ,5,7,3,3,9,10,10,1
1,3,1 ,1,2,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10
中文:
给你n个数
a
1
a_1
a1到
a
n
a_n
an,再给你一个数x,让你按照上面的公式,将[1,x]这x个数插入到
a
1
a_1
a1到
a
n
a_n
an中间,使得上面的哪个公式最小。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
ll t, n, x;
ll A[maxn];
// ifstream in("data.txt");
// ofstream out("res.txt");
int cnt = 0;
int main() {
ios::sync_with_stdio(false);
cin >> t;
while (t--) {
//++cnt;
cin >> n >> x;
ll mi = INT_MAX;
ll ma = -1;
for (int i = 1; i <= n; i++) {
cin >> A[i];
mi = min(mi, A[i]);
ma = max(ma, A[i]);
}
ll ans = 0;
for (int i = 2; i <= n; i++) {
if (A[i] > A[i-1]) {
ans += A[i] - A[i-1];
} else {
ans += A[i-1] - A[i];
}
}
ll a = A[1], c = A[n];
ll tmp;
if (mi > 1) {
tmp = mi - 1;
ll rig = a - tmp;
ll lef = c - tmp;
ll res = 0;
if (tmp - 1 > 0) {
res = tmp - 1;
}
ll mi_sub = min(rig, lef) + res;
if (2 * tmp > mi_sub) {
if (rig < lef) {
ans += rig;
} else {
ans += lef;
}
ans += res;
} else {
ans += 2 * tmp;
}
}
if (x > ma) {
tmp = ma + 1;
ll rig = tmp - a;
ll lef = tmp - c;
ll res = 0;
if (tmp + 1 <= x) {
res = x - tmp;
}
ll mi_sub = min(rig, lef) + res;
// ll val = x * x + x - 3 * ma - 3 - 2 * ma * x + ma * ma;
// ll val = x * x - 2 * ma * x + ma * ma - ma + x;
ll val = (x - ma) * 2;
if (val > mi_sub) {
if (rig < lef) {
ans += rig;
} else {
ans += lef;
}
ans += res;
} else {
ans += val;
}
}
cout << ans << endl;
}
// in.close();
// out.close();
return 0;
}
解答:
数学题,贪心思维
首先要考虑绝对值差求和的性质,比如有3个数[3, 5, 2]
那么按照公式,有
∣
3
−
5
∣
+
∣
5
−
2
∣
|3 - 5| + |5 - 2|
∣3−5∣+∣5−2∣ 得到的结果是2 + 3 = 5
如果插入一个数4,比如插在3和5之间,那么
∣
3
−
4
∣
+
∣
4
−
5
∣
+
∣
5
−
2
∣
|3 - 4| +|4 - 5| + |5 - 2|
∣3−4∣+∣4−5∣+∣5−2∣ 得到的结果还是5。
用符号表示有两个数
[
a
1
,
a
2
]
[a_1, a_2]
[a1,a2]
这里假设
a
1
<
a
2
a_1 < a_2
a1<a2
- 如果插入一个数x,且 x ≥ a 1 x ≥ a_1 x≥a1 且 x ≤ a 2 x ≤ a_2 x≤a2,有 ∣ a 1 − x ∣ + ∣ x − a 2 ∣ |a_1 - x| + | x - a_2| ∣a1−x∣+∣x−a2∣,化简后有 x − a 1 + a 2 − x = a 2 − a 1 x - a_1 + a_2 - x = a_2 - a_1 x−a1+a2−x=a2−a1,即结果不发生变化。
- 同样,考虑 x < a 1 x < a_1 x<a1的情况,为 a 1 + a 2 − 2 x a_1+a_2 - 2x a1+a2−2x ,比较 a 2 − a 1 a_2 - a_1 a2−a1,相当于增加了 2 a 1 − 2 x 2a_1 - 2x 2a1−2x;
- 考虑, x > a 2 x > a_2 x>a2的情况,为 2 x − a 1 − a 2 2x - a_1-a_2 2x−a1−a2,比较 a 2 − a 1 a_2 - a_1 a2−a1,相当于增加了 2 x − 2 a 2 2x - 2a_2 2x−2a2
根据上面三条准则,设计贪心策略如下:
首先,按照公式计算出所有a[i]的绝对值的差的和。
找出a[i]中的最大值max和最小值min,在[1,x]中在[max, min]中间的数全部忽略,因为按照上面的策略第一条,不会对结果造成影响。
接下来判断,判断[1,x]剩余的数,考虑放在a[i]序列两侧,还是放在与a[i]差的绝对值最小的数的两侧,进行一个贪心的判断即可。