SDU week4 B 四個數列(二分)

2021-10-04 01:35:57 字數 2119 閱讀 6377

zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。

當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。

請你幫幫他吧!

input

第一行:n(代表數列中數字的個數) (1≤n≤4000)

接下來的 n 行中,第 i 行有四個數字,分別表示數列 a,b,c,d 中的第 i 個數字(數字不超過 2 的 28 次方)

output

輸出不同組合的個數。

sample input

6-45 22 42 -16

-41 -27 56 30

-36 53 -37 77

-36 30 -75 -46

26 -38 -10 62

-32 -54 -6 45

sample output

5hint

樣例解釋: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

暴力做法是列舉abcd中的每個數,四重迴圈,時間複雜度o(n4),太慢。所以我們列舉a+b,構造出乙個n^2大小的陣列並排序,然後再列舉c+d,列舉c和d的時候計算它的相反數在a和b**現多少次(也就是計算乙個數在有序數列中第一次和最後一次出現的位置),即二分查詢左邊界和右邊界。複雜度為o(n2logn2)

若某個-(c+d)在a+b中不存在,則需返回-1,在主函式裡判斷是否返回-1,若是則不能將範圍段加入。

#define _crt_secure_no_warnings

#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

//#include

#include

#include

#include

using

namespace std;

//快讀

inline

intread()

while

(ch >=

'0'&& ch <=

'9')

x = x *

10+ ch -

'0', ch =

getchar()

;return x * f;

}int a[

4009];

int b[

4009];

int c[

4009];

int d[

4009];

int ab[

16000009];

//a*b

intfind_left

(int x,

int n)

else

if(ab[mid]

> x) r = mid -1;

else l = mid +1;

}return ans;

//返回-1代表不存在

}int

find_right

(int x,

int n)

else

if(ab[mid]

> x) r = mid -1;

else l = mid +1;

}return ans;

//返回-1代表不存在

}int

main()

for(

int i =

0; i < n; i++

)sort

(ab, ab + n * n)

;//對a*b排序

int cur;

int ans=0;

int left, right;

for(

int i =

0; i < n; i++)}

cout << ans;

return0;

}

二分 四個數列

zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。請你幫幫他吧!第一行 n 代表數列中數字的個數,1 n 4000 接下來的 n 行中,第 i 行有...

week4 二分 四個數列

title zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第...

四個數列(二分求解)

小明有四個數列 a,b,c,d,每個數列都有 n 個數字。小明從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。ps 當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第 i 行有四個...