Nezzar and Symmetric Array

C. Nezzar and Symmetric Array

题意:

给定一个n,输入一个长度为2n的数组d,d满足 d i = ∑ j = 1 2 n ∣ a i − a j ∣ di=\sum_{j=1}^{2n}\mid ai-aj\mid di=j=12naiaj,且a数组满足对于任意的$ai $ 1 < = i < = 2 × n 1<=i<=2\times n 1<=i<=2×n都存在一个j 1 < = j < = 2 × n 1<=j<=2\times n 1<=j<=2×n 使得 a i = − a j ai=-aj ai=aj.现在问你是否存在这么一个a数组。

题解:

假设一定存在a数组,那么对a和d数组从小到大排序,观察一下相对关系。
假设当前这个数为a,那么任意一个比a小的数b,对a变成d数组的贡献都是2a, 因为 ∣ a + b ∣ = a + b \mid a+b\mid=a+b a+b=a+b ∣ a − b ∣ = a − b \mid a -b\mid = a-b ab=ab 他俩的和就把b给消掉了。
任意一个比a大的数c对a变成d数组的贡献都是2c因为 ∣ a − c ∣ = c − a \mid a-c\mid=c-a ac=ca, ∣ a + c ∣ = a + c \mid a+c\mid=a+c a+c=a+c 他俩就把a 消掉了,也可以根据画图,相当于曼哈顿距离来理解。
因为ai和-ai对应的d是一样的所以现在我们对d数组进行排序去重,从后往前每个d / 2 再减去前面比他大的数的贡献temp再除以当前有几个数,就可以把对应的a求出来了,当然要特判一下不成立的情况。
当前这个数是奇数不成立,当前这个数出现过奇数次不成立,当前这个数操作完小于等于零也不成立,去重以后不等于原数组的一般也不成立。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 2e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
LL a[N];
int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    int T;
    cin >> T;
    while (T -- ) {
        cin >> n;
        int x = n;
        bool ok = true; 
        map<LL, int> mp;
        for (int i = 1; i <= n * 2; i ++ ) {
            cin >> a[i];
            mp[a[i]] ++;
        }
        sort(a + 1, a + 2 * n + 1);
        n = unique(a + 1, a + 2 * n + 1) - a - 1;
        if (n != x) {
            cout << "NO" << endl;
            continue;
        }
        LL temp = 0;
        for (int i = n; i; i -- ) {
            if (a[i] & 1 || (a[i] / 2 - temp) % i || (a[i] / 2 - temp) <= 0 || mp[a[i]] & 1) {
                ok = false;
                break;
            }
            else  temp += (a[i] / 2 - temp) / i;
        }
        if (ok) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值