LOJ3256「JOI 2020 Final」火災
顯然區間詢問可以變成前綴詢問。
從左往右枚舉右端點,維護單調棧,嘗試維護每個 \(T\) 的答案。
但是對於一個位置,它往前的后綴最大值個數是 \(O(n)\) 的,所以不能暴力。
按照套路,在一個后綴最大值被彈掉的時候計算它的貢獻,那么在詢問的時候就只需要考慮在棧里的元素即可。
對於 \(r-i<T\) 的元素只有 \(i\) 最小的那個元素有可能有貢獻,而再靠前的元素的貢獻可以把 \(pre_r \to r\) 的樹建出來之后 dfs 的過程中維護點到根的信息。其中 \(pre_r\) 是前面第一個大於 \(r\) 的位置。
LOJ3013「JOI 2019 Final」硬幣收藏
不可能會貪心的,這輩子都不可能會貪心的
先把每個硬幣沿着最短路移到矩形內部,這樣顯然不劣。
然后在矩形內部有 \(2n\) 個球和洞要兩兩配對。顯然可以看做球和洞一起移動。
從左往右貪心。考慮最左邊的兩個格子,把在同一位置的球和洞匹配掉(顯然不劣)之后:
- 上下都只有洞,那么都往右走。
- 上下都只有球,同樣都往右走。
- 一邊有球一邊有洞,不妨設上球下洞,球>洞。如果洞沒有被這里的球匹配完,那么就有右邊的球走到洞里,這里的球往右邊走。可以調整為這里的球往下走,右邊的球往上走,代價不變。
所以在第三種情況中,可以直接用球把洞匹配完,然后把球往右移。
進行 \(n\) 步這樣的操作即可得到答案。
LOJ3014「JOI 2019 Final」獨特的城市
我的想法:
顯然,對於一個點,合法的城市全都在它到它的最遠點的路徑上。而最遠點只能是直徑端點之一,所以把兩個端點分別提為根做一次。
那么此時一個點就只需要關心它到根這條路徑上的點了。
這條路徑上哪些點是合法的呢?把 從這條路徑上的點開始的往下的路徑 往上拍,沒被拍到的點即為合法的。
在 dfs 的時候維護這個過程。dfs 到 \(x\) 的時候,用一個棧維護路徑上所有合法點對應的顏色,每個顏色只記錄最淺的位置(因為最淺的位置最不容易被刪掉),棧內顏色按最淺的位置的深度排序。
為了求 \(x\) 的答案,只需要二分求棧內深度較淺的不會被子樹拍到的顏色有幾個。
dfs 進某一個兒子的時候,把其他兒子的子樹往上拍的考慮進去,會把棧里的元素彈掉一些,也可以二分求出位置。然后要把自己的顏色嘗試加進去。
那么又有一個問題:我怎么知道我的顏色現在是否還在棧里呢?
對每一個顏色記錄它在棧中的位置即可,如果位置 \(\le\) 棧的大小那么說明在棧中,否則不在。
加入 \(x\) 的時候會使棧的大小加 1 ,要把原來在這個位置的顏色標記為不在棧中,即把它在棧中的位置定為 \(\infty\) 。
回溯的時候撤銷所有操作。
題解做法:
前面基本上是一樣的,還是在於怎么求鏈上合法的不同顏色個數。
用棧維護沒被拍掉的點,用桶維護每種顏色的出現次數。
長鏈剖分,先往重兒子走(用輕兒子的最大深度彈棧),再往輕兒子走(用重兒子彈棧)。
然后復雜度就對了?就對了?就對了?你在玩我?
如果按我的想法,每次 dfs 之后還撤銷,那么復雜度顯然是不對的。
但是注意到一個性質:如果往一個兒子走,子樹內的鏈把自己的祖先拍掉了,那么往別的兒子走的時候這些祖先還是要被拍掉的,也就是說它們已經廢了。
所以是不用撤銷的,只需要 dfs 一個兒子后再把自己加進去一次即可,因為自己是不一定要被拍掉的。
總入棧次數是 \(O(n)\) 的,所以復雜度 \(O(n)\) 。
LOJ2335「JOI 2017 Final」足球
最怕這種看起來莫名其妙的題了……
不學OI的同學總覺得這種題是最好做的
在最優解中,如果一個人曾經控過球且現在沒有控球,那么以后都不可能控球。證明是因為運球和空跑的代價是一樣的。
然后我就不會了啊啊啊啊……
可以猜到這么一個做法:把每個位置拆點,分別表示 沒人控球、有人控球、在往上/下/左/右飛 ,然后沒人控球向有人控球連的邊權為 \(C\times 最近的人\) ,跑最短路。
容易發現最優解一定被包含了,但是怎么證明這樣跑出來的方案合法呢?具體而言,怎么保證一個人不會產生分身,跑去一個地方踢了一腳,瞬移回原來位置,又去另一個位置踢了一腳呢?
沒看到哪里有證明,於是自閉了……
Rose_max 老大給了個證明,不過看不太懂,所以棄了。
LOJ2336「JOI 2017 Final」繩
由於染色的代價和厚度有關,所以可以發現折完再染不如一開始就染好。
考慮一個顏色序列什么時候合法。顯然只能有兩種顏色。
在每一次折的時候,要么是把邊上的顏色連續段長度減 1 ,要么是把對稱點所在的連續段長度砍半,且變到邊上去,較短的那一邊刪掉,其他連續段不變。
所以初始狀態除了兩端的連續段長度都必須是偶數,並且容易證明這是充要條件。
然后這個條件也就等價於對於我們重點關心的那個顏色,每一段長度為偶數,且起始位置的奇偶性相同。
所以對於每一種顏色,枚舉起始位置的奇偶性,判斷每一段是否要往前/往后生長(可以發現此時即使兩段合並了也沒有問題,因為不可能重疊),然后在剩下的格子里挑出現次數最多的顏色和它一起。
怎么除了第一步以外每一步都想不到啊 /kk
LOJ2345「JOI 2016 Final」領地
先特判掉一個周期走回原地的情況。
否則,相當於是這個路徑每次會向着一個向量的方向平移,最后得到許許多多的路徑的交。
把只靠這個向量就可以互相平移到的格子設為一組,每組分別做。顯然對於所有組的格子,邊界上的被初始路徑經過的點數之和是 \(O(n)\) 的。
對於這一組格子,把四個角的被標記的點分別拿出來,然后一個點會覆蓋后面連續 \(K\) 個位置,可以變成 \(O(n)\) 個線段,最后再用歸並把這 4 組線段求個交即可。
以上是口胡,因為網上沒看到有題解。
LOJ2346「JOI 2016 Final」斷層
直接維護看起來莫名其妙的,考慮把最后在地面的位置標記一下,倒着做,維護它們原來在哪里。
手畫一畫就會發現,好像此時每次操作都是對一個前綴/后綴進行操作。
證明:
- 對於操作 1 ,一個點會往左下滑當且僅當 \(x-y\) 較小,操作結束后被操作的點 \(x-y\) 不變, \(x+y\) 減小。
- 對於操作 2 ,一個點會往右下滑當且僅當 \(x+y\) 較大,操作結束后被操作的點 \(x+y\) 不變, \(x+y\) 增大。
在初始情況下,點的 \(x-y,x+y\) 都遞增,所以任意時刻都是遞增的,任意操作都是對一個前綴/后綴進行。
所以就線段樹維護一下坐標即可。
LOJ2727「JOI 2015 Final」舞會
顯然可以二分答案,變成 01 串。顯然編號沒有任何用。
考慮操作的過程,相當於每次把最靠前的三個合並成一個丟到最后面去。
一開始模擬一下這個過程,把合並出來的作為三個的父親,即可建出一棵樹。
在樹上設 \(dp_x\) 表示讓 \(x\) 子樹合並出一個 1 要多少個 1 即可。
LOJ2760「JOI 2014 Final」裁剪線
第一眼看上去好像毫無思路,於是考慮掃描線。
從上往下掃,維護被豎線分開的段之間的連通性。
加入一條豎線的時候,把一個段分成兩個段,但這兩個段是連通的。
刪除一條豎線的時候,把相鄰的兩個段合並,相應的連通性也可能會改變,用並查集維護即可。
加入一條橫線的時候,會把一個區間的段刪除,換成新的和別的段都不連通的段。其中刪除的段中每有一整個連通塊被刪除則答案加一。
朴素地做好像是 \(O(n^2)\) 的。
把加入橫線時加入的段設為 “平凡的” ,加入或刪除一條豎線的時候影響的段設為 “特殊的” 。
顯然特殊的段的個數是 \(O(n)\) 的,而加入橫線的時候可以很容易把平凡的段的貢獻算上,對於特殊的段暴力統計,並且特殊的段被橫線刪掉后就會變成平凡的。
所以數據結構維護一下即可做到 \(O(n\log n)\) 。
以上都是口胡,網上只看到一篇題解,不過思路似乎是這樣的。
LOJ2765「JOI 2013 Final」 冒泡排序
好像和這個基本一模一樣。
顯然交換之后的代價就是逆序對數;顯然在特判掉原本就有序之后,如果交換 \(i<j,h_i>h_j\) ,那么貢獻是 \(1+2\sum_{k=i}^j [h_j<h_k<h_i]\) 。
所以 \(i\) 一定是前綴最大值, \(j\) 一定是后綴最小值。
此時可以證明決策單調性,用分治+主席樹在 \(O(n\log^2 n)\) 的復雜度內做出來。
然而另一個做法更暴力也更快……
對於一個點 \((x,h_x)\) ,可以求出哪些 \((i,j)\) 會包含它,顯然是個矩形。
那么用掃描線即可得到矩形覆蓋的最大值,\(O(n\log n)\) 。
這篇博客終於更完了……