UVa:10125 Sumsets

最容易想到的办法是枚举四个数,当然肯定会超时。
于是想到一个办法S=a+b+c,三个循环+二分查找S,结果也超时。
然后发挥非凡想象力的时候到了,S-a=b+c,两个循环+二分查找b+c。这样时间复杂度可以大大降低。

可以枚举b+c的和,注意这里会有n*(n+1)/2种情况,所以开数组要大点。另外要考虑到S,a,b,c不能重了,所以用结构体同时把b,c的序号也保存下来。

还有要注意二分查找前要排序。
这里要求最大的S,所以可以先将该集合排序,最后从大到小枚举S和a,出现的第一个符合的S和a就是答案。

 

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Sum_two
{
    int a,b;
    int val;
};
int BSsearch(Sum_two *A,int low,int high,int key)
{
    while(low<high)
    {
        int mid=(high+low)/2;
        if(A[mid].val==key) return mid;
        else if(key<A[mid].val) high=mid-1;
        else low=mid+1;
    }
    return -1;
}
bool cmp(Sum_two a,Sum_two b)
{
    return a.val<b.val;
}
Sum_two sum[500505];
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        int a[1005]={0},ans=0;
        bool p=false;
        for(int i=0;i<n;++i)
        scanf("%d",&a[i]);
        if(n>=4)
        {
        sort(a,a+n);
        int N=0;
        for(int i=0;i<n-1;++i)
         for(int j=i+1;j<n;++j)
         {
             sum[N].val=a[i]+a[j];
             sum[N].a=i;sum[N].b=j;
             N++;
         }
         sort(sum,sum+N,cmp);
         for(int i=n-1;i>=0&&!p;--i)
          for(int j=n-1;j>=0&&!p;--j)
          {
               int key=a[i]-a[j];
               int x;
              if(i!=j&&(x=BSsearch(sum,0,N,key))!=-1)
              {
                  if(sum[x].a==i||sum[x].b==j) continue;
                  if(sum[x].a==j||sum[x].b==i) continue;
                  ans=a[i];
                  p=true;
              }
          }
        }
        if(p) printf("%d\n",ans);
        else printf("no solution\n");
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值