[CF1698C]3SUM Closure

做题时间:2022.6.29

\(【题目描述】\)

给你 \(t(t\leq 1000)\) 个长度为 \(n(\sum n\leq 2\times 10^5)\) 的序列 \(a\) 。判断每一个序列是否满足 \(\forall i,j,k\) , \(1\leq i<j<k\leq n\) ,存在 \(l(1\leq l\leq n)\) 满足 \(a_i+a_j+a_k=a_l\)

\(【输入格式】\)

第一行一个 \(t\)
接下来 \(2t\) 行,每组数据第一行一个整数 \(N\) ,第二行 \(N\) 个整数表示 \(a\)

\(【输出格式】\)

对于每一组数据一个 \(YES\)\(NO\)

\(【考点】\)

分类讨论

\(【做法】\)

sb分类讨论

首先可以看得出来,若正数或负数过多,就会出现越加越多(少)的情况,不可能满足。经过验证可以发现,若正数或负数的个数必须 \(\leq2\)

好像可以暴力,但可能还有很多的0,考虑到0的个数太多对于结果并没有影响,当0的个数大于2时,和等于2的效果相同。

这样一来序列长度就控制在了 \(6\) 以内,直接暴力。

\(【代码】\)

#include<cstdio>
using namespace std;
const int N=2e5+50;
int a[N],n,t;
int b[N],ed;
bool Check()
{
    int neg=0,pos=0,zer=0;
    ed=0;
    for(int i=1;i<=n;i++){
        pos+=(a[i]>0),neg+=(a[i]<0),zer+=(a[i]==0);
        if(a[i]!=0) b[++ed]=a[i];
    }
    if(neg>2||pos>2) return false;//正数或负数的个数>2不符合要求
    if(zer>=1) b[++ed]=0;
    if(zer>=2) b[++ed]=0;
    
    //暴力
    for(int i=1;i<=ed;i++){
        for(int j=i+1;j<=ed;j++){
            for(int k=j+1;k<=ed;k++){
                int t=b[i]+b[j]+b[k];
                bool q=false;
                for(int l=1;l<=ed;l++){
                    if(t==b[l]){q=true;break;}
                }
                if(!q) return false;
            }
        }
    }
    return true;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        if(Check()) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
posted @ 2022-07-06 21:40  lxzy  阅读(52)  评论(0)    收藏  举报