赞
踩
传送门
一、题意: 现在有一个长度为2n的数组d,它可能是由一个长度为2n的数组a转变而来的,而数组a是一个对称数组(不存在重复的数字,并且对于每个a[i],总能找到一个a[j]==-a[i]),而d[i]是该位置的a[i]与其他所有2n-1个位置的元素的差的绝对值之和。
问是否存在这样一个数组a,若存在输出YES,否则NO
二、思路: 经过多组样例测试我们可以发现一个规律:
当|a[i]|>|a[j]|时,a[i]与a[j]和与-a[j]的差的绝对值之和会等于2a[i]。
假设|a[i]|为a数组中的最大值,因为不存在相同的元素,所以a[i]与其他任何一个a[j]和-a[j]的差的绝对值都会等于2a[i],再加上与-a[i]的差的绝对值,在d[i]的位置将会等于(2*a[i])*n,那么我们就可以通过d[i]来获得a[i]。
三、方法: 我们可以将d数组按降序排序,假设遍历到d[i]位置,我们可以假设将1-i-1位置的元素都已经删除,那么d[i]位置将会是数组的最大值的位置,那么就可以按照上述方法来求出a[i]的值。
因为d[i]也包括了与比a[i]大的值的差的绝对值,所以在遍历过程中要记录下前2a[1]+…2a[i-1]的值,用d[i]减去即可。
求出的a[i]如果不是0,不是重复,不是负数,则符合条件,否则直接跳出。
cpp代码
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #define int long long using namespace std; int d[200004]; map<int, int>ma,vis; int cmp(int x, int y) { return x > y; } signed main() { int t; scanf("%lld", &t); while (t--) { ma.clear(); vis.clear(); int n; scanf("%lld", &n); int flag = 1, ans = 0; for (int i = 1; i <= 2 * n; i++) { scanf("%lld", &d[i]); ma[d[i]]++; if (ma[d[i]] == 1)ans++; else if (ma[d[i]] == 2)ans--; if (d[i] % 2 != 0) { flag = 0; } } if (!flag) { printf("NO\n"); continue; } if (ans) { printf("NO\n"); continue; } sort(a + 1, a + 1 + 2 * n, cmp); ans = 0; for (int i = 1; i <= 2 * n; i += 2) { if ((d[i] - ans) % ((n - (i - 1) / 2) * 2) == 0 && d[i] - ans > 0) { int p = (d[i] - ans) / ((n - (i - 1) / 2) * 2); if (!vis[p]) { ans += ((d[i] - ans) / ((n - (i - 1) / 2) * 2)) * 2; vis[p] = 1; } else { flag = 0; break; } } else { flag = 0; break; } } if (flag)printf("YES\n"); else printf("NO\n"); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。