题解:CF2171B Yuu Koito and Minimum Absolute Sum
ORaRF_QuantuY_L · · 题解
题目分析
有一个数组
注意这个求和可以化简:
所以,题目实际上是在问:能否通过选择非负整数填充
::::info[注意]
- 如果
a_1 和a_n 都已经确定,那么S 就是固定的,我们无法再通过中间元素改变S 。 - 如果
a_1 或a_n 是-1 ,我们可以通过选择它们的值来改变S 。 - 中间的元素对
S 没有直接影响,但会影响字典序。 ::::
最小化 |a_n - a_1|
- 如果
a_1 和a_n 都已知,那么S \gets |a_n - a_1| 已固定。 - 如果
a_1 已知,a_n 未知,我们可以选a_n \gets a_1 使S \gets 0 (因为a_n 可以是非负整数)。 - 如果
a_n 已知,a_1 未知,可以选a_1 \gets a_n 使S \gets 0 。 - 如果两者都未知,我们可以选
a_1 \gets a_n \gets 0 使S \gets 0 。 - 但注意:我们填充时,所有元素必须是非负整数。
因此:
- 如果
a_1 和a_n 中至少一个是-1 ,我们总可以令它们相等(取已知的那个值,或取0 ),使S \gets 0 。 - 如果两者都已知且不同,那么
S 就是它们的差的绝对值,无法改变。
所以最小可能的
字典序最小
在
令
为了字典序最小:
- 如果
a_1 已知,则a_n \gets a_1 。 - 如果
a_n 已知,则a_1 \gets a_n 。 - 如果都未知,则
a_1 \gets a_n \gets 0 。
然后中间的元素:我们填充
对于每个
不,因为中间值不影响
但是:我们必须保证所有
因此,策略是:
- 确定
a_1 和a_n 的值(使它们相等,用已知值或0 )。 - 对于其他
-1 ,填0 。 - 如果某位置已知,就保持原值。
情况 2: a_1 和 a_n 都已知且不同
此时
我们无法改变
同样,中间未知元素直接填
算法实现
如果
- 如果
a_0 已知,则a_{n-1} \gets a_0 。 - 如果
a_n-1 已知,则a_0 \gets a_{n-1} 。 - 如果都未知,则
a_0 \gets a_{n-1} \gets 0 。 -
否则(两者都已知): -
对于中间未知元素($-1$),填 $0$。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5;
int a[N];
void solve() {
int n;
cin >> n;
for(int i = 0;i < n + 10;i++){
a[i] = 0;
}
for (int i = 0; i < n; i++) {
cin >> a[i];
}
if (a[0] == -1) {
if (a[n-1] == -1) {
a[0] = 0;
a[n-1] = 0;
} else {
a[0] = a[n-1];
}
} else {
if (a[n-1] == -1) {
a[n-1] = a[0];
}
}
int minn;
if (a[0] == -1 || a[n-1] == -1) {
minn = 0;
} else {
minn = abs(a[n-1] - a[0]);
}
for (int i = 0; i < n; i++) {
if (a[i] == -1) {
a[i] = 0;
}
}
cout << minn << "\n";
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << '\n';
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
AC记录。