1. 程式人生 > >[HDU 4334] Trouble (分治+二分查詢)

[HDU 4334] Trouble (分治+二分查詢)

HDU - 4334
給你五個陣列,每組 N個元素 (N<=200)
問是否能在五個數組裡各選一個數,使得和為0
思路是分治,然後再二分查詢,降低複雜度

1) 算出 S1S2所有元素的和的情況並排序,對 S3S4亦是如此 O(N2)
2) 列舉 S3S4的和陣列與 S5的和的情況
再在 S1S2的和數組裡找其相反數 O(N2Nlog(N2))

所以最終時間複雜度就為 O(N3log(N))

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; typedef pair<int,int> Pii; #define MST(a,b) memset(a,b,sizeof(a)) #define CLR(a) MST(a,0) #define LL long long #define ULL unsigned long long #define pow2(a) a*a
int maxx(int a,int b){return a>b?a:b;} int minn(int a,int b){return a<b?a:b;} int abss(int a){return a<0?(-a):a;} const int maxn=210; int N; LL inpt[2][maxn]; LL res[2][maxn*maxn]; int Get(int); bool Exist(int,int,LL); int main() { int T; scanf("%d", &T); for(int ck=1; ck<=T; ck++) { CLR(inpt);CLR(res); scanf
("%d", &N); int siz1=Get(0); int siz2=Get(1); bool ok=0; for(int i=0; i<N; i++) { LL now; cin>>now; for(int j=0; j<siz2; j++) { if(ok) break; LL val=now+res[1][j]; if(Exist(0,siz1,-val)){ok=1;break;} } } puts(ok?"Yes":"No"); } return 0; } int Get(int np) { for(int i=0; i<N; i++) cin>>inpt[0][i]; for(int i=0; i<N; i++) cin>>inpt[1][i]; int siz=0; for(int i=0; i<N; i++) { for(int j=0; j<N; j++) { res[np][siz++]=inpt[0][i]+inpt[1][j]; } } sort(res[np],res[np]+siz); siz=unique(res[np],res[np]+siz)-res[np]; return siz; } bool Exist(int np, int siz, LL val) { int l=0,r=siz; while(l+1<r) { int mid=(l+r)>>1; if(res[np][mid]==val) return 1; if(res[np][mid]>val) r=mid; else l=mid; } return 0; }