1. 程式人生 > >uva 1152 二分查詢+中途相遇法

uva 1152 二分查詢+中途相遇法

題意:

       給定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;
}