【CF1798D】Shocking Arrangement
【CF1798D】Shocking Arrangement
Description
给出一个长度为
你需要重排这个数列,使得重排后满足
多组数据,
Analysis
整蛊题。
首先如果
否则考虑从左到右构造新数列,维护新数列的前缀和
- 如果
s \geq 0 ,则在剩余未加入的数中随便选择一个非正数添加到新数列末尾。 - 如果
s < 0 ,则在剩余未加入的数中随便选择一个负数添加到新数列末尾。
因为保证了数列之和为
考虑这样构造的正确性:注意到
而任何区间的和都可以写成两个前缀和相减的形式。设
Code
写代码时把正数和非负数分别排了个序,现在看起来似乎是不必要的。
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
int T;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
for (std::cin >> T; T; --T) {
int n;
std::cin >> n;
std::vector<int> a(n), b, c;
std::generate(a.begin(), a.end(), []() { int x; std::cin >> x; return x; });
if (*std::max_element(a.begin(), a.end()) == 0) {
std::cout << "No\n";
continue;
}
std::cout << "Yes\n";
for (auto i : a)
if (i < 0) b.push_back(i);
else c.push_back(i);
std::sort(b.begin(), b.end());
std::sort(c.begin(), c.end(), std::greater<int>());
int sum = 0;
for (int i = 1, j = 0, k = 0; i <= n; ++i) {
if (sum >= 0 && j < b.size()) {
std::cout << b[j] << ' ';
sum += b[j++];
} else {
std::cout << c[k] << ' ';
sum += c[k++];
}
}
std::cout << '\n';
}
}