HDU 2141 Can you find it? (二分法)

题目大意: 

给你三组数字,从每组中选一个数字,看选出的三个数字相加的和能不能等于所给数字;

点我题目在这里

题目思路

由于每组数最多有500个,要查询的数字最多会有1000个,三个三个挨个找显然是不现实的。 我们可以想到,可以任选两组求和,然后遍历剩下的一组,对得到的和数组进行二分.。这样可以大大降低时间复杂度(同时,记得把得到的和数组进行去重,可以减少计算的次数,因为题目只要求你判断是否可以满足,相同的数字效果相同)

踩的坑

   因为要去重还要排序 (二分是去二分有序序列),第一反应就是用set,因为感觉去重好麻烦啊(果然是自己太菜).......可是一直MLE我也很是无奈,后来才知道unique这个函数(好好用) , 而且看大神的写法自己用sort后自己再手动去重也很简单。

题目收获:

①函数unique:unique()是c++标准库里的库函数,功能是去除相邻元素的重复元素(只保留一个),把重复元素放在了数组的最后面。最后返回的是去重之后的尾地址。一般的用法:如果去重之后想要得到数组的大小,就要再减去数组的首地址;

例如:

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int main(void)
{
    int a[10]={1,1,3,4,2,23,4,5,5,5};
    sort(a,a+10); //先对数组排序
    int k=unique(a,a+10)-a; //k为已经去重后的数组的大小
    for(int i=0;i<k;i++)  //输出数组
    {
        if(i)
            cout<<" ";
        cout<<a[i];
    }
    cout<<endl;
    return 0;
}

运行结果:

但是要特别注意:如果想要去重比较干净,一定要先把数组排好序,因为unique()去除的是 相邻 元素的重复元素,如果把上面代码的sort注释掉,就会出现下面的结果:

②手动对一个数组去重的简洁写法:

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int main(void)
{
    int a[10]={1,1,3,4,2,23,4,5,5,5};
    sort(a,a+10);
    //int k=unique(a,a+10)-a;
    int len=0;
    for(int i=1;i<10;++i)//手动去重
    {
        if(a[i]!=a[len])
            a[++len]=a[i];
    }
    int k=len; //最后去重后的数组大小
    for(int i=0;i<=k;i++)
    {
        if(i)
            cout<<" ";
        cout<<a[i];
    }
    cout<<endl;
    return 0;
}

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 505
#define maxnn 505*505

using namespace std;
int a[maxn],b[maxn];
int tol[maxnn];
int l,n,m,s;
//set<int>se;

bool cal(int k,int ri,int j)
{
    //printf("%d.....\n",tol[1]);
    for(int i=0;i<l;i++)
    {
        int left=0;int right=k-1;
        while(right>=left)
        {
            int mid=(right-left)/2+left;
            if(tol[mid]+a[i]==ri)
            {
                //res[j]=1;
                //printf("mid:%d   %d+%d=%d\n",mid,tol[mid],a[i],ri);
                return 1;
            }
            else if(tol[mid]+a[i]>ri)
                right=mid-1;
            else if(tol[mid]+a[i]<ri)
                left=mid+1;
           // printf("mm\n");
        }
    }
    return 0;
}
void init()
{
    //se.clear();
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(tol,0,sizeof(tol));
}
int main(void)
{
    int kase=1;
    int sum;
    int c,r;
    while(~scanf("%d%d%d",&l,&n,&m))
    {
        init();
        //memset(res,0,sizeof(res));
        for(int i=0;i<l;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        int k=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d",&c);
            for(int j=0;j<n;j++)
            {
                sum=c+b[j];
                //se.insert(sum);
                tol[k++]=sum;
            }
        }
        sort(tol,tol+k);
        k=unique(tol,tol+k)-tol;
        printf("Case %d:\n",kase++);
        scanf("%d",&s);

        for(int i=0;i<s;i++)
        {
            scanf("%d",&r);
            printf("%s\n",cal(k,r,i)?"YES":"NO");
        }

    }
    return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81182888