uva 1152 二分查詢+中途相遇法
阿新 • • 發佈:2019-01-26
題意:
給定4個n元素集合,要求分別從中選取一個元素a,b,c,d使得a+b+c+d=0.問,有多少種說法?
題解:
根據紫書演算法,我們計算出a+b的所有和,放入vector陣列中,同時計算c+d的所有和,放入vector陣列中,之後暴力列舉a+b的所有和,在c+d和陣列中二分查詢-(a+b),這裡需要注意的是原始的二分查詢只會找到一個數據,陣列中可能會有多個-(a+b),我們需要判斷。PE了好幾次,uva了格式很嚴格!
程式碼:
#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef long long LL; vector<LL> sumA,sumB; int solve(int mid,LL ans) { //cout<<mid<<ans<<endl; int count=0; int i=mid+1; int j=mid-1; while(sumB[i]==ans) { count++; i++; } while(sumB[j]==ans) { count++; j--; } return count; } int main() { vector<LL> data[4]; int T; cin>>T; LL num,tmp; while(T--) { cin>>num; for(int i=0;i<num;i++) { for(int j=0;j<4;j++) { cin>>tmp; data[j].push_back(tmp); } } LL sum1,sum2; for(int i=0;i<num;i++) { for(int j=0;j<num;j++) { sum1 = data[0][i]+data[1][j]; sum2 = data[2][i]+data[3][j]; sumA.push_back(sum1); sumB.push_back(sum2); } } LL sizA = sumA.size(); LL sizB = sumB.size(); int ans=0; sort(sumB.begin(),sumB.end()); for(int i=0;i<sizA;i++) { LL se = -sumA[i]; int right=sizB-1; int left =0; while(right>=left) { int mid = (right+left)>>1; if(sumB[mid]>se){ right=mid-1; } else if(sumB[mid]<se) { left=mid+1; } else if(sumB[mid]==se){ //cout<<sumB[mid]<<se<<endl; ans++; int o=solve(mid,se); ans+=o; break; } } } cout<<ans<<endl; if(T!=0) cout<<endl; sumA.clear(); sumB.clear(); for(int j=0;j<4;j++) { data[j].clear(); } } return 0; }