HDU 2141 can you find it 二分
Posted cn_XuYang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 2141 can you find it 二分相关的知识,希望对你有一定的参考价值。
1.题意:给出三组数,给出一个数X,试问是否能从三个数组中各选一个数,A,B,C使得X=A+B+C
2.分析:题设的输入数据为先是依次给出三组数的长度L、N、M,下面三行给出三组数的内容,再下面一行给出要查询的数X的个数S,最后S行是依次给出S个查询值X。其中1<=L, N, M<=500, 1<=S<=1000。首先若是朴素的考虑三个数组的任意组合,那么有L*N*M种组合,结合数据规模O(N*3)看太大了,所以将上式变形为A+B=X-C,考虑前两个数组的任何组合,有L*N种,这样对于每一个X,等式右边就有M种情况,遍历这M种情况,对于右边每一种取值,二分寻找左边L*N种取值,这样就能在O(NlogN)的规模下求解。
3.代码:Tips:数据中包含负数,且注意运算过程中有可能超过int的范围
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 const int MAXN=505; 6 int COUNT=0; 7 int L,N,M,S; 8 long long A[MAXN],B[MAXN],C[MAXN]; 9 long AB[MAXN*MAXN],snum[2*MAXN]; 10 void Init() 11 { 12 for(int i=0;i<L;i++) 13 scanf("%lld",&A[i]); 14 for(int i=0;i<N;i++) 15 scanf("%lld",&B[i]); 16 for(int i=0;i<M;i++) 17 scanf("%lld",&C[i]); 18 scanf("%d",&S); 19 int temp=0; 20 for(int i=0;i<L;i++) 21 for(int j=0;j<N;j++) 22 AB[temp++]=A[i]+B[j]; 23 sort(C,C+M); 24 sort(AB,AB+L*N); 25 for(int i=0;i<S;i++) 26 scanf("%lld",&snum[i]); 27 } 28 bool judge(long long n) 29 { 30 for(int i=0;i<M;i++) 31 { 32 int l=0; 33 int r=N*L-1; 34 if((C[i]<n-AB[r])||(C[i]>n-AB[l])) continue;//不用longlong就会WA 35 while(l<=r) 36 { 37 int mid=l+(r-l)/2; 38 if(AB[mid]+C[i]==n) return true; 39 else if(AB[mid]+C[i]>n) r=mid-1; 40 else l=mid+1; 41 } 42 } 43 return false; 44 } 45 void Solve() 46 { 47 printf("Case %d:\n",++COUNT); 48 for(int i=0;i<S;i++) 49 { 50 long long temp=snum[i]; 51 if(judge(temp)) printf("YES\n"); 52 else printf("NO\n"); 53 } 54 } 55 int main() 56 { 57 while(scanf("%d%d%d",&L,&N,&M)!=EOF) 58 { 59 Init(); 60 Solve(); 61 } 62 return 0; 63 }
以上是关于HDU 2141 can you find it 二分的主要内容,如果未能解决你的问题,请参考以下文章
HDU 2141 Can you find it? 二分查找
HDU 2141 Can you find it? (二分)