優先佇列例題

2021-10-19 11:33:36 字數 3113 閱讀 8938

本文摘自部落格,歡迎前往部落格以獲得更好的體驗。

有兩個長度都是 n 的序列 a 和 b ,在 a 和 b 中各取乙個數相加可以得到 n

2n^2

n2個和,求這 n

2n^2

n2個和中最小的 n 個。

輸入格式

第一行乙個正整數 n;

第二行n個整數 a

ia_i

ai​ , 滿足 ai≤

ai+1

a_i \le a_

ai​≤ai

+1​ 且 ai≤

10

9a_i \le 10^9

ai​≤10

9;第三行n個整數 b

ib_i

bi​ , 滿足 bi≤

bi+1

b_i \le b_

bi​≤bi

+1​ 且 bi≤

10

9b_i \le 10^9

bi​≤10

9;1 ≤n

≤100000

1 \le n \le 100000

1≤n≤10

0000

輸出格式

輸出僅一行,包含n個整數,從小到大輸出這n個最小的和,相鄰數字之間用空格隔開。

題意很明了,我們只需要將 a 和 b 序列數字的和壓入堆中,並取前 n 個和即可。但是,很明顯,在遇到資料過於 毒瘤 大的情況時,顯然時間複雜度會達到 o(n

2log

n)

o(n^2logn)

o(n2lo

gn) ,顯然超時。

因為兩個序列是遞增的,如若 ai+

bj

a_i + b_j

ai​+bj

​ 沒有放入優先佇列,那麼 ai+

bj+1

a_i + b_

ai​+bj

+1​ 呢?

答案是很顯然易見的,並不會放入優先佇列。因為 b 序列滿足 bi≤

bi+1

b_i \le b_

bi​≤bi

+1​ ,所以 ai+

bj+1

>ai

+b

j>q.

top(

)a_i + b_ > a_i + b_j > q.top()

ai​+bj

+1​>ai

​+bj

​>q.

top(

) 。所以 ai+

bj

a_i + b_j

ai​+bj

​ 沒有放入優先佇列時,ai+

bj+n

(n

>0)

a_i + b_(n > 0)

ai​+bj

+n​(

n>0)

也都不會被放入,可以直接 break ,跳轉到 ai+

1+bi

a_ + b_i

ai+1​+

bi​ 繼續列舉。

時間複雜度證明

第一行至多掃完它的 1

1\dfrac

11​ ,第二行變為 1

2\dfrac

21​由此類推,第i行最多 1i(

1≤i≤

n)

\dfrac(1 \le i \le n)

i1​(1≤

i≤n)

合在一起,共 11+

12+⋯

+1

n\dfrac+\dfrac+\cdots+\dfrac

11​+21

​+⋯+

n1​尤拉證明過,上面的無窮級數的增長率為 o(l

nn

)o(lnn)

o(lnn)

的因此,總複雜度為 o(n

logn

lnn)

o(n\ logn\ lnn)

o(nlog

nlnn

) ,即 o(n

log2

n)

o(nlog^2n)

o(nlog

2n) 的,證畢

#include#include#includeusing namespace std;

priority_queueq;

int n,a[100005],b[100005],ans[100005];

int main()

else}}

}for(int i = n;i >= 1;i--)

for(int i = 1;i <= n;i++) printf("%d ",ans[i]);

return 0;

}

當 i∗j

>

ni*j>n

i∗j>

n 時,ai+

bj

a_i+b_j

ai​+bj

​ 一定不是前 n 小的數。

因為兩個序列均有序,所以如果 x

<=i

x<=i

x<=i

且 y<=j

y<=j

y<=j

那麼 ax+

by

+b

ja_x+b_yax

​+by

​​+bj

​ 。於是至少有 i∗j

i*ji∗

j 個數小於等於 ai+

bj

a_i+b_j

ai​+bj

​ 。當 i∗j

>

ni*j>n

i∗j>

n 時,一定有多餘 n 個數小於等於 ai+

bj

a_i+b_j

ai​+bj

​ ,所以 ai+

bj

a_i+b_j

ai​+bj

​ 一定不是前 n 小的數。

核心**if(i * j >= n) break;

待補充

經典優先佇列例題整理

time limit 2000ms memory limit 65536kb 64bit io format lld llu submit status description 我們的小夥伴bingo真的很調皮,他在上課的路上看到樹上有個鳥窩,他就想去把他捅下來,但是鳥窩很高他夠不到,於是他就到處找...

關於佇列(還有廣度優先搜尋的例題)

本博文的目錄 1 佇列 2 佇列的例題 3 廣度優先搜尋的例題 1 佇列 佇列是什麼?佇列是一種特殊的線性表,與棧不同,這種線性表只允許在表的前端 我們稱為front或head 進行刪除操作,在表的後端 我們稱作rear或tail 進行插入操作。所以又叫f first i in f first o ...

深度優先搜尋例題

輸入m行,n列的陣列,給定起點座標x,y和終點座標w,z,求從起點到終點的路徑數。規定可以前後左右移動,但是下一步的值必須比當前值大。示例 輸入 4 5 0 0 1 0 0 0 0 2 0 0 0 0 3 4 0 0 0 7 5 0 0 2 3 2 輸出 2 解法 其實就是很簡單的深度優先搜尋 in...