この質問への質問リンク\(n \ leq 1000 \)、まず最初に3つの値を直接列挙してから、2つの点で\(4 \)の数値を求めますが、複雑さは明らかに許容できません。次に、複雑さを軽減し続けることができます。。。これらの数値を前処理すると、\(n ^ 2 \)は2つの数値のグループのすべてのケースを見つけて、両端から個別に列挙できます。2つの数値の合計は0で、確かに1つは小さく、1つは大きく、 2つの列挙からの数値のすべての組み合わせを列挙すると、すべてのケースが確実に列挙されます。したがって、列挙が真ん中に達する前に、要件を満たす回答があるかどうかを判断します。
const int maxn = 1e6+10;
struct INFO {
int a, b;
ll sum;
void add(int x, int y, ll z) {
a = x, b = y, sum = z;
}
} info[maxn];
ll arr[maxn]; int kase;
int main(void) {
int n;
scanf("%d", &n);
for (int i = 0; i<n; ++i) scanf("%lld", &arr[i]);
for (int i = 0; i<n-1; ++i)
for (int j = i+1; j<n; ++j)
info[kase++].add(i, j, arr[i]+arr[j]);
sort(info, info+kase, [](INFO x, INFO y){
return x.sum < y.sum;
});
int l = 0, r = kase-1;
while(l<r) {
if (info[l].sum+info[r].sum == 0 && info[l].a!=info[r].a && info[l].a!=info[r].b && info[l].b!=info[r].a && info[l].b!=info[r].b) {
printf("Yes\n");
return 0;
}
else if (info[l].sum+info[r].sum<0) ++l;
else --r;
}
printf("No\n");
return 0;