浅谈YKH算法

显然,对于小范围数据,我们最容易想到的就是nn的暴力做法 ,但是对于大范围数据暴力是不行的。这时候我们就像到了优化。如果能把它优化到nn能过的数据就行了。我们知到两个大数相加肯定是一个更大的数,所以我们只要把多余的大数去掉即可。(对于超过1000的n,我们就把它砍到1000)保险起见先sort两遍,然后砍数据,最后得出来<=1000000的数我们再sort一遍。输出前n个即可。下面是代码。

#include<bits/stdc++.h>
using namespace std;
int n,nn,a[100005],b[100005],c[25000005],tot;
int read()
{
    int x=0;char c;bool f;
    f=true;
    c=getchar();
    if (c=='-') f=false;
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    if (f==false) x=x*-1;
    return x;
}
int main()
{
//  freopen("xulie.in","r",stdin);
//  freopen("xulie.out","w",stdout);
    n=read();
    for (int i=1;i<=n;i++)
    a[i]=read();
    for (int i=1;i<=n;i++)
    b[i]=read();
    sort(1+a,1+a+n);
    sort(1+b,1+b+n);
    nn=n;
    tot=0;
    if (n>1000) nn=1000;
    for (int i=1;i<=nn;i++)
    for (int j=1;j<=nn;j++)
    {
        tot++;
        c[tot]=a[i]+b[j];
    }
    sort(1+c,1+c+tot);
    for (int i=1;i<=n;i++)
    printf("%d ",c[i]);
    return 0;
}

  但是,这种做法可能会有反例(虽然目前没找到,程序也能过所有数据)。我们这时候就可以用大根堆优化,先把a[1]与所有的bi做一遍加法,得出n个初始值,然后再从a[2]开始与所有的b[i]做加法,一旦找到一个a[j]+b[i]是比堆头大的,就直接退出然后输出。下面是代码。

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int x=0;char c;bool f;
    f=true;
    c=getchar();
    if (c=='-') f=false;
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    if (f==false) x=x*-1;
    return x;
}
priority_queue<int> k;
int n,a[100010],b[100010],ans[100010];
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) b[i]=read();
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    for(int i=1;i<=n;i++) k.push(a[1]+b[i]);
    for(int i=2;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(k.top()>a[i]+b[j]){
                k.pop();
                k.push(a[i]+b[j]);
            }else break;
    for(int i=n;i>=1;i--) ans[i]=k.top(),k.pop();
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    puts("");
    return 0;
}

  注意细节!!!

posted @ 2019-02-24 15:02  xzjds  阅读(533)  评论(0编辑  收藏  举报