51nod 1105 第K大的數

2021-10-10 02:38:38 字數 2786 閱讀 9581

1105 第k大的數

1.0 秒 131,072.0 kb 20 分 3級題

陣列a和陣列b,裡面都有n個整數。

陣列c共有n^2個整數,分別是:

a[0] * b[0],a[0] * b[1] … a[0] * b[n-1]

a[1] * b[0],a[1] * b[1] … a[1] * b[n-1]

a[n - 1] * b[0],a[n - 1] * b[1] … a[n - 1] * b[n - 1]

是陣列a同陣列b的組合,求陣列c中第k大的數。

例如:a:1 2 3,b:2 3 4。

a與b組合成的c為

b[0]  b[1]  b[2]
a[0] 2 4 6

a[1] 3 6 9

a[2] 4 8 12

共9個數。

輸入第1行:2個數n和k,中間用空格分隔。n為陣列的長度,k對應第k大的數。(2 <= n <= 50000,1 <= k <= 10^9)

第2 - n + 1行:每行2個數,分別是a[i]和b[i]。(1 <= a[i],b[i] <= 10^9)

輸出輸出第k大的數。

輸入樣例

3 21 2

2 33 4

輸出樣例

9【分析】

一道二分+驗證的題目。

由於驗證也可以二分,所以作為二分套二分的經典題型。

這題有諸多細節:

①二分時對於等於號是否要加上的把握

②精度問題(卡了半天精度,實際上需要轉化一下去掉除號)

第一步,意識到不能暴力…

第二步,注意到排序後帶來的一些可能的優化,比如利用單調性,比如二分。於是考慮進行二分。

我們假設(二分)第k

kk大的數字是mid

midmi

d,我們怎麼直到這個mid

midmi

d比真實值大還是比真實值小呢?

我們統計比mid大的數字,定義為ans

ansan

s,如果ans

>=k

ans>=k

ans>=k

,說明前面有至少k

kk個比mid

midmi

d大的,mid

midmi

d一定偏小了,可以將mid

midmi

d調大,即,往右區間二分;如果ans

<

kansan

s<

k,說明前面比mid

midmi

d大的不足k

kk個,則mid

midmi

d要往小了走,這裡有個等於號的問題,等於號應該放在哪個分支?顯然,等於k

kk時,mid

midmi

d還是偏小的,所以放在第乙個分支了。

第三步,如果得知大於k

kk的數字個數?總不能直接暴力吧,這裡,我們只需二分這個大於k

kk的值,同樣設為mid

midmi

d,接下來將兩個序列的其中乙個排序,如樣例:

1 、2

、3

1、2、3

1、2、32、3

、4

2、3、4

2、3、

4我們列舉第乙個序列,先列舉到1

11,然後令x=m

id/1

x = mid/1

x=mid/

1,這樣,我們只需二第二個序列中二分x

xx的位置,即可找到具體比x

xx大的數字個數;然後列舉2

22,同樣令x=m

id/2

x = mid/2

x=mid/

2,然後在序列中二分;然後列舉3

33……這樣一來做到nlo

gn

nlogn

nlog

n的複雜度,統計出大於mid

midmi

d的數字個數。

還有一種方法更好,將兩個序列都排序,列舉乙個序列,另乙個序列開乙個變數表示大於x

xx的位置,由於具有單調性,這個變數只會往一邊移動,可以做到o(n

)o(n)

o(n)

。兩種**都附上了,相對而言二分套二分的做法更具代表性,雖然速度不如第二種驗證,但是頗具練習價值。

第四步,本題有精度問題,就是lon

glon

glonglong

longlo

ng和m id

/a[i

]mid/a[i]

mid/a[

i]的問題,對於lon

glon

glonglong

longlo

ng,自己分析開哪些就可以了,對於除法,通過移項轉化成乘法,不要卡精度,卡了半個早上無果…

【ac**】兩個check都附上了

#include

#include

#define maxn 50039

using

namespace std;

int n, k, a[maxn]

, b[maxn]

;int

check

(long

long g)

ans +

= n-l;

}return ans}/*int check(long long g)

return ansint

main()

printf

("%lld"

, r)

;return0;

}

51Nod 1105 第K大的數

acm模版 這裡使用二分套二分查詢即可。一般的二分查詢是通過下標範圍查詢,而二分套二分是為了求兩個陣列組合乘積的問題,查詢第k大的值,這裡我們需要通過資料的範圍查詢,而不是下標的範圍,這裡需要兩次快排。需要強調的一點是資料範圍問題!一定要使用long long型,避免資料溢位!include inc...

51nod 1105 第K大的數

1105 第k大的數 基準時間限制 1 秒 空間限制 131072 kb 分值 40 難度 4級演算法題 陣列a和陣列b,裡面都有n個整數。陣列c共有n 2個整數,分別是a 0 b 0 a 0 b 1 a 1 b 0 a 1 b 1 a n 1 b n 1 陣列a同陣列b的組合 求陣列c中第k大的數...

51nod 1105第K大的數

1105 第k大的數 基準時間限制 1 秒 空間限制 131072 kb 分值 40 難度 4級演算法題 陣列a和陣列b,裡面都有n個整數。陣列c共有n 2個整數,分別是 a 0 b 0 a 0 b 1 a 0 b n 1 a 1 b 0 a 1 b 1 a 1 b n 1 a n 1 b 0 a ...