Values whose Sum is 0(四列數和爲零問題(二分基礎))

題目來源:[NWPU][2014][TRN][5]二分和貪心A題

http://vjudge.net/contest/view.action?cid=49586#problem/A

作者:npufz

問題:給定四列數,共有N行,(N<4000),求算出在任意一列裏面挑選出一個數字,使四個數字的和爲零的情況有多少種,每個數字的大小不超過2的28次方。

代碼:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
long int b[16000000],c[16000000];
int main()
{
    int n;
    long int a[4000][4],cnt,i,j,num1,num2;
    long long int sum;
    scanf("%d",&n);
    for(i=0; i<n; i++)
        scanf("%ld%ld%ld%ld",&a[i][0],&a[i][1],&a[i][2],&a[i][3]);
    cnt=0;
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            b[cnt]=(0-a[i][0]-a[j][1]);
            cnt++;
        }
    cnt=0;
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            c[cnt]=a[i][2]+a[j][3];
            cnt++;
        }
    sort(c,c+cnt);
    sum=0;
    for(i=0; i<cnt; i++)
    {
        num1=(lower_bound(c,c+cnt,b[i])-c);
        num2=(upper_bound(c,c+cnt,b[i])-c);
        if(c[num1]==b[i])
        {
            sum+=(num2-num1);
        }
    }
    cout<<sum<<endl;
    return 0;
}

反思:一開始的時候覺得枚舉能過,就試圖用有限制條件的枚舉,就是先求算前兩列的和,再求算後兩列的和,然後對兩列和分別進行升降序排列,然後就控制兩列和的加法順序,只對能夠是和爲零的情況進行遍歷,就果斷超時了,可見和爲測試數據和爲零的情況特別的多,然後改用二分,結果對c++標準庫的UPPER_BOUND和LOWER_BOUND不夠熟悉,沒有理解它是知道那個元素的插入位置,就WA了,經過對找到元素是不是進行判斷後,就又超時了,可能是CIN比SCANF費時間,就改爲SCANF,同時去掉一個排列,只對一列和進行排列,就又WA了,經大神指點,原來排序和查找時漏掉了最後一個元素

教訓:SCANF更省時,UPPER_BOUND和LOWER_BOUND只是找到插入的位置,和那個元素在集合中存不存在沒有關係,對集合排序和查找不能漏掉任何元素


發佈了42 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章