一棟大樓中 \(10^5\) 個人緊急疏散。大樓可以被視作網格圖(正檢視),有三個區域,由兩個寬為 1 的樓道隔開。走出樓道最下面即為離開。同一時刻乙個位置只能有乙個人。左右區域的人不能互相串。每個人每一秒能移動一格。問所有人離開所需的最小時間這題正解比暴力好寫(一般貪心題都這樣),因此考場上沒想到貪心就很難受。
首先考慮中間沒有人的情況。這是個經典套路了。我們可以把每個人單獨的花費時間算出來,然後如果花費時間相同,則它們會衝突,需要讓乙個人的時間 + 1;如果還出現相同,就繼續 + 1,直到沒有相同的為止。這個可以用並查集來維護。
然後考慮中間有人的情況。如果人非常少,那麼我們可以暴力列舉每個人去左邊還是去右邊。
現在考慮一般情況。考慮到這道題實際上是要求「最晚走的人的走的時間最小」,於是考慮二分答案,保證每個人的時間都在 \(mid\) 以內即可。我們設 \(l_i\) 表示第 \(i\) 個人去左邊的時間,\(r_i\) 表示第 \(i\) 個人去右邊的時間。然後我們將所有人按照 \(r_i\) 從大到小排序,如果能去左邊就盡量去左邊,否則去右邊
感性證明:顯然時間小更優,那麼以後的所有人對於「去右邊」都比當前這個人優。如果能夠把當前這個人安排到左邊,那麼就算以後有個人也想安排到左邊被佔了,他還可以來右邊,並且肯定比當前這個人的選擇更多。
看來,「想不到怎麼貪心就排個序」的方法還是挺有用的。
另外,此題的離散化也需要一些小技巧。暴力的 \(n^2\) 離散化顯然不行,直接用 \(map\) 也感覺多個 \(log\) 不太穩(或許也可以手寫 unordered_map)。考慮到有用的值只可能是計算出來的時間或者計算出來的時間 + 一些人數。我們可以把最劣情況模擬一遍,搞出所有的有用時間點,並且中間還需要空一些格仔。顯然,這樣的時間點數量不會超過 \(4n\)。不太好描述,直接看**吧:
inline void lsh()
for (register int i = 1; i <= n; ++i)
nd[i].t1 = lower_bound(lh + 1, lh + 1 + ltot, nd[i].t1) - lh,
nd[i].t2 = lower_bound(lh + 1, lh + 1 + ltot, nd[i].t2) - lh;
}
啟智樹提高組Day3 T3 pancake
現有 n 個線段,第 i 個線段長度為 l i 現最多可以切 k 刀,只能在整數字置切。要求最小化切完後所有線段的長度的平方和。又有 q 次操作,每次將 k 加一或減一,或者新加一段長為 l i 的線段。每次問最小的平方和。n,q,l i,k le 10 5 保證答案不爆 long long 首先 ...
啟智樹提高組Day4T3 2的冪拆分
問把 n 拆分成2的冪的和的形式的方案數。注意拆分是無序的,即 2 0,2 2,2 1,2 0 和 2 0,2 0,2 1,2 2 是一種方案。n le 10 定義 s k n sum i k 部分下取整符號可能有遺漏。首先通過打表發現前幾項是 從0開始 1,1,2,2,4,4,6,6,10,10,...