本来想做dp题的,上网找分类,偶然看到这道题,据说无数人WA。。
上去一看3000/15000
在长度为1000的序列中找到w,x,y,z,使得a[w]+a[x]+a[y]=a[z]
其中序列元素互不相同,数值范围-1<<29到1<<29
A了以后证实不用long和long long
一般网上的解法都是n^3枚举+log(n)二分
对于1<=n<=1000来说太吓人了。。。
想了很久,想到先预处理n*n个sum=a[w]+a[x],然后枚举a[z]和a[y],二分找sum,
预处理的时候需要记录对于某个sum,需要记录得到它的a[w]和a[x],这样避免枚举到sum+a[y]=a[z],其中sum是由a[y]或者a[z]得到的。
我目测时间复杂度是n^2log(n^2),但是在和ac代码对拍的时候发现明显比n^3log(n)慢得多,,不知道为什么,求大牛指教。
代码:
#define X 1010 #include<stdio.h> #include<algorithm> using namespace std; struct Sum{ int a,b,c; }sum[X*X]; bool cmp(Sum x,Sum y){ if(x.c!=y.c)return x.c<y.c; if(x.a!=y.a)return x.a<y.a; if(x.b!=y.b)return x.b<y.b; } int bi(int x,int r){ int l=0,m; while(l<r){ m=l+r>>1; if(sum[m].c<x)l=m+1; else r=m; } return r; } int a[X]; int main(){ // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int i,j,n,m,k,top; while(scanf("%d",&n),n){ for(i=0;i<n;i++) scanf("%d",&a[i]); if(n<4){puts("no solution");continue;} sort(a,a+n); for(i=top=0;i<n;i++) for(j=i+1;j<n;j++){ sum[top].a=a[i]; sum[top].b=a[j]; sum[top].c=a[i]+a[j]; top++; } sort(sum,sum+top,cmp); k=X; for(i=n-1;i>=0;i--) for(j=n-1;j>=0;j--) if(i!=j){ m=bi(a[i]-a[j],top); while(sum[m].c==a[i]-a[j]){ if(sum[m].a!=a[j]&&sum[m].b!=a[j] &&sum[m].a!=a[i]&&sum[m].b!=a[i]) {k=i;break;} m++; } if(k==i)i=j=-9; } if(i==-10)printf("%d\n",a[k]); else puts("no solution"); } return 0; }
别人的代码很明显for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)lower_bound()
我的代码很明显for(i=0;i<n;i++)for(j=0;j<n;j++)lower_bound()
其中while循环可以证明最多循环3次
因为对于固定的sum 只可能sum.a==a[i]或者sum.a==a[j]
实在找不出为什么慢了。。。
作者:zzxyyx_1 发表于2013-1-15 21:39:18 原文链接
阅读:22 评论:0 查看评论