浅谈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; }
注意细节!!!