51Nod 1267 4个数和为0(二分)

给出N个整数,你来判断一下是否能够选出4个数,他们的和为0,可以则输出”Yes”,否则输出”No”。
Input
第1行,1个数N,N为数组的长度(4 <= N <= 1000)
第2 - N + 1行:A[i](-10^9 <= A[i] <= 10^9)
Output
如果可以选出4个数,使得他们的和为0,则输出”Yes”,否则输出”No”。
Input示例
5
-1
1
-5
2
4
Output示例
Yes

把每两个数的和存下来,并且还要存下每个数的下标,防止选的数字重复,然后直接二分找就可以了。

一开始TLE了两次,还以为是算法写的有问题,后来发现数组开小了。。。51Nod对于数组开小不是报RE,而是报TLE。。。

求和的数组大概开到10^6吧。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long int LL;
const int MAXL(1e6);
const int MAX(0x3f3f3f3f);
int a[MAXL+50];
int ans[MAXL+50];
struct node
{
    int index1,index2;//组成和的两个数字的下标
    int data;
}s[MAXL+50];
bool cmp(struct node p,struct node q)
{
    return p.data<q.data;
}
bool judge(struct node p,struct node q)//判断下标
{
    if(p.index1==q.index1)
        return false;
    if(p.index1==q.index2)
        return false;
    if(p.index2==q.index1)
        return false;
    if(p.index2==q.index2)
        return false;
    return true;
}
int Binary_search(int left,int right,int target)
{
    int index=0;
    while(left<=right)
    {
        int mid=(left+right)/2;
        if(s[mid].data<=target)
        {
            left=mid+1;
            index=mid;
        }
        else
            right=mid-1;
    }
    return s[index].data==target?index:-1;
}
int main()
{
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    int len=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            s[len].index1=i;
            s[len].index2=j;
            s[len++].data=a[i]+a[j];
        }
    }
    sort(s,s+len,cmp);
    for(int i=0;s[i].data<=0;i++)//终止条件,data<=0,可以节省很多时间
    {
        int x=fabs(s[i].data);
        int index=Binary_search(i,len-1,x);
        if(index==-1)
            continue;
        if(judge(s[i],s[index])==true)
        {
            cout<<"Yes"<<endl;
            return 0;
        }
    }
    cout<<"No"<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值