切換
舊版
前往
大廳
主題

ZeroJudge - e407: 買包子 (Bun) 解題心得

Not In My Back Yard | 2019-10-02 23:31:36 | 巴幣 4 | 人氣 211

題目連結:


題目大意:
第一列給定一正整數 q  (q ≦ 3 × 10 ^ 5),代表接下來有 q 列輸入,每列代表一個指令。其可能為下列兩者之一:
1 c ,代表在當前隊伍的尾端加入一個需要 c 個包子的客人。
2 k ,代表在當前隊伍中的人都得到 k 個包子。
(0 ≦ c 、 k ≦ 10 ^ 12)

當有一個客人得到他所需要的包子數(得超過也沒關係)後,還不能離開隊伍。要等到他前面的人都離開(也就是他變成了隊伍的頭)時,才能離開隊伍。

對於每個 2 k 指令輸出:發完包子使得每個人拿到 k 個新包子後,已經得到自己想要的數量但還不能離開隊伍的有多少人?



範例輸入:
輸入範例一:
13
1 5
1 3
1 1
1 6
2 2
1 6
2 1
2 2
2 3
1 8
1 3
2 6
1 3

輸入範例二:
15
1 32
1 18
1 13
1 6
2 8
2 7
1 12
2 9
1 32
2 7
2 7
1 13
2 15
1 32
2 18


範例輸出:
輸出範例一:
1
2
0
0
1

輸出範例二:
1
2
3
4
0
1
0


解題思維:
把每個人的需求量用優先佇列(Priority queue) N 存起來(佇列前端需要是最小值,而不是預設儲存的最大值);同時也需要另一個普通的佇列(Queue)H 用來表示原本的隊伍之樣態(隊伍順序)。

但是因為如果每個人的需求量直接放入優先佇列 N 的話,可能反而跑到優先佇列 N 的頂端(最小),但實際上前面的人已經快拿到目標數量。但是一拿到 k 個包子就將佇列 N 裡所有的人需求量減去 k 個很不實際(很慢)。

因此,我們可以採取將後來的人需求量加上已經發出去的包子數量。如此,便可以判斷前面的人是否快達標以及不用每一次發包子就減去相應的值。

接著是每次發包子時,判斷目前已經發出去的包子數量(包含這次所有 k 的總和,不是指所有人拿到的包子總數)有無大於優先佇列 N 的頂端(也就是當前隊伍最小值)。如果有的話,就將其移出優先佇列 N 裡,並將其在原本的隊伍之位置放到另一個優先佇列 S 裡,用以表示達標的人們,且越靠近隊伍的頭的人越前面(優先佇列頂端也是存最小值)。

然後再判斷這次發包子後,隊伍的頭(設編號 i)可不可以離開隊伍了(因為是頭,所以達標就可以離開了)。如果可以,那麼剛剛優先佇列 S 應該也會有編號 i ,將其移出該優先佇列 S 中且繼續判斷優先佇列 S 的下一個最小值是否為編號 i + 1 的人。如果是,該人也可離開優先佇列 S 。

重複以上步驟直到 S 為空、隊伍空了或是目前的頭離不開所以後面的人也走不開。此時優先佇列 S 的大小即是所求。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

屠屠
不明原因我的程式比你的慢
不過可以確認的是記憶體使用量只有一半不到
https://ideone.com/xorcY3
2020-12-06 21:50:19

相關創作

更多創作