首先我们观察到存在 a[i] == 0 时,一定输出 "NO"

排除掉 a[i] == 0 的情况后,我们可以发现,a[i] 不是正就是负

我于是定性地画出了 “图像”

alt

我们可以把正数分一个组,负数分一个组

可以想到没有正数或是没有负数时,不可能 存在和为 0 的情况

之后就是判断 交界处两个数加起来 可不可能 不为 0

假设 正数组中存在一个数 a,负数组中存在一个数 b,满足 a + b == 0

我们要想办法避免这种情况,就想着把 ab 替换掉,然而当正数或负数不同的数量超过 1 时,我们就有可供选择的其他数 (alternatives),使交界处的和不为 0,此时我们已经完成了构造

也就是 当只有一种正数和一种负数,且这两个数和为 0,才能满足 "NO" 的条件,我们可以直接判掉

剩下来的直接输出 "YES"

本题,我使用了两个 set 维护,当然也可以使用 4 个 bool 变量记录,此处不再赘述

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    unordered_set<int> zh, fu;  // 正数、负数 set
    bool bl = false;  // 特判是否存在 0
    for (int i = 0; i < n; ++i) {
        int tmp;
        cin >> tmp;
        if (!bl) {  // 已经存在 0,就直接忽略后面的操作,只要读完数据就行
            if (tmp == 0) {
                bl = true;
            } else if (tmp > 0) {
                zh.emplace(tmp);
            } else {
                fu.emplace(tmp);
            }
        }
    }
    if (bl) {  // 有 0 直接输出 NO
        cout << "NO";
        return 0;
    }
    int s = zh.size(), t = fu.size();
    if (s == 0 || t == 0) {  // 先判空,防止 *zh.begin() 或 *fu.begin() 为空
        cout << "YES";
        return 0;
    }
    int a = *zh.begin(), b = *fu.begin();
    if (zh.size() == 1 && fu.size() == 1 && a + b == 0) {
        cout << "NO";
        return 0;
    }
    cout << "YES";  // 其余情况都是 YES
}