题意
给定一个整数序列 A A A 和 K K K,判断是否能够通过重排 A A A 中的元素使 A A A 变成一个好的序列,即:
这个好的序列 A A A 里所有小于 K K K 的前缀和必须在所有大于或等于 K K K 的前缀和之前出现。
如果可以,先输出 Yes,然后输出重排后的结果;如果不能,输出 No。
分析
这道题的思路是贪心,要对 K K K 进行分类讨论:
-
如果 K ≥ 1 K \ge 1 K≥1,那么这种一定是有解的,直接输出 A A A 数组的升序排序即可,因为排序后当 A i < k A_i<k Ai<k 时, A i A_i Ai 一定在前面的位置,反之则在后面。
-
如果 K < 1 K<1 K<1,那么设 a n s ans ans 为 A A A 数组所有数字的和,判断 a n s ≥ k ans \ge k ans≥k,则 A i > k A_i>k Ai>k 的数在前面,故使用降序排序输出。但是如果 a n s < k ans<k ans<k,就是说连 A A A 数组所有数的和都小于 K K K 的话,那么一定无解,输出
No即可。
还有一点要注意:记得开 long long,不然稍微大点的数据会炸掉因为这个问题硬控了我一次提交。
Code
// AT_arc179_a.Partition
#include <cstdio>
#include <algorithm>
using namespace std;
// 记得开 long long,数据范围
long long n, k, ans, a[200005];
// 排序降序函数
bool cmp (int x, int y) {
return x > y;
}
int main() {
scanf ("%lld%lld", &n, &k);
for (int i = 1; i <= n; i++) {
scanf ("%lld", &a[i]);
// 所有数字总和
ans += a[i];
}
// 分类讨论 k 的范围
if (k >= 1) {
// 升序排序
sort (a + 1, a + n + 1);
printf ("Yes\n");
for (int i = 1; i <= n; i++) printf ("%lld ", a[i]);
printf ("\n");
} else {
// 判断如果全部的总和大于等于 k
if (ans >= k) {
// 降序排序
sort (a + 1, a + n + 1, cmp);
printf ("Yes\n");
for (int i = 1; i <= n; i++) printf ("%lld ", a[i]);
printf ("\n");
// 都不行,输出 No
} else printf ("No");
}
return 0;
}
完结撒花。
930

被折叠的 条评论
为什么被折叠?



