D. Imbalanced Arrays
D. Imbalanced Arrays
Ntarsis has come up with an array of non-negative integers.
Call an array of integers imbalanced if it satisfies the following:
- , ,
- there are no two indices () such that ,
- for each , there are exactly indices () such that , where and are not necessarily distinct.
Given the array , Ntarsis wants you to construct some imbalanced array. Help him solve this task, or determine it is impossible.
Input
Each test contains multiple test cases. The first line contains the number of test cases (). The description of the test cases follows.
The first line of each test case has a single integer ().
The next line contains integers ().
It is guaranteed that the sum of across all test cases does not exceed .
Output
For each test case, output "NO" if there exists no imbalanced array.
Otherwise, output "YES". Then, on the next line, output integers where for all — an imbalanced array.
Example
input
5 1 1 4 1 4 3 4 3 0 1 0 4 4 3 2 1 3 1 3 1
output
YES 1 NO YES -3 1 -2 YES 4 2 -1 -3 YES -1 3 -1
Note
For the first test case, is an imbalanced array. This is because for , there is exactly one () where .
For the second test case, it can be shown that there exists no imbalanced array.
For the third test case, . The array is an imbalanced array.
- For and , there exists no index such that .
- For , there is only one index such that ().
Another possible output for the third test case could be .
解题思路
首先从前两个条件可以知道我们只能从每一对中选择一个数,比如选了就不能再选,但可以重复选。
如果存在合法的数组,那么一定存在一个绝对值最大的数,假设为。如果,那么一定有;否则如果,那么一定有。同时中不可能同时存在和,否则就会推出和,就与第二个条件矛盾了。
因此只要中存在或者(不能同时存在),那么就在最大的数对中(即)取相应的元素赋值给,然后再把去掉,继续处理剩余的元素。
为此可以先对按照值的大小进行排序,然后设置两个指针和分别表示的最左端和最右端,然后判断是否满足上面所说的条件即可。其中如果去掉的最右端的,由于,因此中剩余的元素都要减去,而删除并不需要改变剩余元素的值。因此判断是否满足的条件就是的值是否为,其中就是去掉右端的元素数量。
AC代码如下,时间复杂度为:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 1e5 + 10; 7 8 int a[N], p[N]; 9 int ans[N]; 10 11 void solve() { 12 int n; 13 scanf("%d", &n); 14 for (int i = 1; i <= n; i++) { 15 scanf("%d", a + i); 16 p[i] = i; 17 } 18 sort(p + 1, p + n + 1, [&](int i, int j) { 19 return a[i] < a[j]; 20 }); 21 for (int i = 1, j = n, k = n; i <= j; k--) { 22 if (!(a[p[i]] - (n - j)) ^ (a[p[j]] - (n - j) == j - i + 1)) { 23 if (!(a[p[i]] - (n - j))) ans[p[i++]] = -k; 24 else ans[p[j--]] = k; 25 } 26 else { 27 printf("NO\n"); 28 return; 29 } 30 } 31 printf("YES\n"); 32 for (int i = 1; i <= n; i++) { 33 printf("%d ", ans[i]); 34 } 35 printf("\n"); 36 } 37 38 int main() { 39 int t; 40 scanf("%d", &t); 41 while (t--) { 42 solve(); 43 } 44 45 return 0; 46 }
参考资料
Codeforces Round 887 (Div 1, Div 2) Tutorial:https://codeforces.com/blog/entry/116940
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17672504.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效