Vijos[1983]NOIP2015Day2T3 運輸計劃 transport LCA
題目鏈接Vijos
題目鏈接UOJ
轉載一個大佬的題解:
點擊這裏->銀牌爺題解
主要考察二分查找、樹上倍增、貪心、“樹上前綴和”。
題目是一顆樹,要求將一條邊的權值變為0,使得所有運輸計劃的最大時間最小。
直覺告訴我們,這是一個樹上倍增的題目,但是它卻不像前幾年的 Day2T3 開車旅行那樣純倍增,或許更像疫情控制一些,倍增只是輔助算法,還需要配合其他算法。
由於要使所有運輸計劃的最大時間最小,不難想到二分答案的方法。
使C(t)表示是否可以改造一條邊,使得改造之後所有運輸計劃中最長的時間不大於t。這是慣用伎倆,用二分的的話,我們就可以確定一個變量t,正因為有了這個t,我們才能有的放矢的進行貪心或是幹別的。
如何判斷C(t)呢?在開始的時候用倍增預處理出所有計劃的時間,如果小於等於t,就可以忽略,如果大於t,那麽就要考慮在其路徑上改造一條邊。
由於所有時間大於t的計劃都要改造一條邊,問題就變為了求所有時間大於t的計劃的路徑交集,改造其中一條最大的邊,看看去掉這條邊之後,是否可以滿足條件。
問題來了,如何求交集呢?
這裏給出兩種方法,一種是模擬求交集。一種是利用樹上前綴和求交集。如果設total為超出時間t的方案數量,邊e?i??經過的次數cnt?i??。對於每個超出時間t的方案,將其路徑中邊的cnt加1。最後,所有cnti=totalcnt?i??的邊就是我們要求的的交集。
然而每次給每條邊加一肯定是不現實的,所以我們要想出一個高效的方法,來維護邊被經過的次數。
這個方法像極了2012年NOIP的借教室,不過是樹上的版本。我們先看看借教室的怎麽處理區間加減的。
如果要對一段連續區間[a,b)同時加上一個值,只需在開始處加上這個值,在結束後減去這個值,維護前綴和就行了。看上去應該是這樣的:若初始都是0,讓連續區間[a,b)同時加上一個值m之後,前綴和 即為元素i的值。下面是前綴和:
如果有多組加減,也不會沖突。
同樣的,在樹上,我們用s?i??來表示頂點i到其父親的這條邊被經過的次數,v?i??用於記錄頂點信息。
對於每個點對(a,b),我們將v?a??+