需要寫一下的題:
- [x] 「JOI 2017 Final」繩
- [x] 「JOI 2016 Final」斷層
- [x] 「JOI 2016 Final」領地
- [ ] 「JOI 2013 Final」 冒泡排序
- [ ] 「JOI 2015 Final」城牆
- [ ] 「JOI 2019 Final」獨特的城市
- [ ] 「JOI 2020 Final」奧運公交
- [ ] 「JOI 2020 Final」火災
爲什麼 JOI Final 的題前三個都是水,最後兩個超勇的。
Update:一道後兩個題都做不出來 「大哭」
JOI 2013 Final
「JOI 2013 Final」JOIOI 塔
小米同步賽 T1 和這題類似,當時沒見過都自閉了 😭
考慮二分答案,那麼儘可能在最後面選出來 mid 個 OI,然後前面拼 I 和 J 即可。
「JOI 2013 Final」 冒泡排序
有趣的思路題。不交換的答案就是逆序對數,我們把點化爲二維座標上的點 \((i,h_i)\),交換的兩點一定滿足 \(i < j,h_i>h_j\),這樣逆序對數會減少矩形內點個數 * 2 + 1,我們找到最大的矩形即可。不難發現左上角一定是一個前綴最大值,右上角一定是一個後綴最小值,可以使用決策單調性來做(更普遍),但在這題中有更棒的性質,左上角是向右上走的斜線,右下角也是,考慮每個點的貢獻,發現對左上斜線的一個區間可以右下斜線的一個區間選出來兩個點形成的矩形有 1 的貢獻,可以抽象到另外一個二維平面上,矩形加查詢最大值即可。
JOI 2014 Final
「JOI 2014 Final」飛天鼠
以爲是神仙建圖,結果是神仙貪心。
發現上升和下降的代價再哪裏都一樣,我們在需要上升和下降的時候再進行操作。
這代表着我們從起點開始跑最短路,(在貪心的前提下)到達一個點的最短路和到達一個點時最高的高度是“統一的”,也就是最短路可以確定高度。考慮到達一個點最高的高度非 0,說明到達這個點之前沒有使用上升操作,顯然越高最短路也越小。如果高度爲 0,直接記錄最短路即可。
「JOI 2014 Final」裁剪線
參考題解:https://blog.csdn.net/qq_42101694/article/details/104775768
考慮使用從下至上掃描線解決(先掃豎線入點,然後橫線,然後豎線出點),掃到一個豎線入點,不會改變連通情況,將經過的地方分裂爲兩個塊。掃到一個橫邊,將完全覆蓋掉的區域新建連通塊,表示和原先完全分裂。掃到一個豎線出點,兩個區域連爲一個連通塊。不可以暴力新建連通塊的,我們採用在平衡樹上打 Tag 的方式。碰到豎線直接下傳 Tag,碰到二操作將答案加上區間內“被打上標記而沒有新建節點”塊的個數。
細節較多,但如果精細的實現起來並不複雜,是一道不錯的題目。
JOI 2015 Final
這場略微簡單一點啊。
「JOI 2015 Final」舞會
一開始看錯題了 😅
樹形結構永遠的神,考慮二分答案,對於給定的序列來說,我們將其看成一個 01 串,發現可以建出一個決策樹出來,設 \(dp[x]\) 表示節點爲 1 則至少要放置多少個 1,合併上去爲 1 的條件就是有至少兩個都爲 1。
「JOI 2015 Final」城牆
巧妙的二維數點問題,這裏數正方形我們採用數左上角和右下角 pair 的個數。
枚舉對角線,那麼對於一個左上角,我們求出它向右向下最遠延申到哪裏,兩者取 min 設爲 \(y_i\),其橫座標設爲 \(x_i\),右下角橫座標爲 $ y_j$,最遠向左延申到的橫座標設爲 \(x_j\) ,兩個點可以組成一個 pair 當且僅當 \(x_j \le x_i,y_j \le y_i\),不難發現是一個二維數點問題,掃描線解決即可。
JOI 2016 Final
「JOI 2016 Final」領地
設一輪過後 x 變化 \(p\),y 變化 \(q\),特判 \(dx = 0,dy =0\) 的情況。不妨設 \(dx > 0\),否則 \(\mathbb{swap}(x, y)\)。
對於被走過的一個點 \((x,y)\) 來說,可以表示爲 \((x'+rp,y'+rq)\),其中 \((x'< p)\)。爲什麼要這樣表示?因爲我們可以發現,r 的範圍是一些區間,區間的總和是 \(\Theta(n)\) 級別的!
所以可以用一個二元組 \((x,y)\) 和一個區間集合 \([l_1,r_1],[l_2,r_2]\cdots [l_n,r_n]\) 來表示 \((x+tp,y+tq)(t \in [l_i,r_i])\) 的點。
我們考慮如何統計答案,枚舉矩形的左下角,考慮 \((x,y),(x+1,y),(x,y+1),(x+1,y+1)\),取它們區間集合的並集即可(如果 \(x = p\) 要把區間集合平移一下),暴力枚舉複雜度就是對的,實現可以暴力一些以減少代碼量。
一種可能的實現是按左端點歸併,維護右端點最遠到達多少,每次答案就是 \(\max(\min(newl, \min(r)) - nowl,0)\)
「JOI 2016 Final」斷層
由於初始點太多了,我們倒着考慮,這樣就可以做到 \(\Theta(n^2)\) 了,思考如何優化這個過程:
- 對於 \(x - y \le k\) 的點,對 \(x,y\) 都減去 L。
- 對於 \(x + y \ge k\) 的點,對 \(x\) 加上 L,\(y\) 減去 L。
我們直接用一個二元組 \((A,B)=(x+y,x-y)\) 表示這個點,重新考慮這個過程:
- 對於 \(B \le k\) 的點,A -= 2L
- 對於 \(A \ge k\) 的點,B += 2L
發現初始狀態是 \((A,B)=(i,i)\) 單調遞增,經過我們這兩個操作依然單調遞增!
所以說就可以二分到對應的位置然後區間加減即可,可以用樹狀數組優化代碼量和常數。
樹狀數組上二分這種科技原來早就有啊!
JOI 2017 Final
具體來說,對於一個點 x 來說,找到最近的快車點,然後找到最近的中快車點,最後做慢車到達。
所以可以設出暴力 dp,算出每一段放 k 箇中快車點得到的最大收益是多少,可以獲得 \(48 \%\)。
這其實是一個揹包問題,每個段的收益函數是一個單減函數,所以直接用堆維護即可。
「JOI 2017 Final」足球
發現 W,H 沒有想象的那麼大,看起來大概可以類似最短路 dp 的做法,記錄毬在 x, y 処最少要多少代價,同時發現性質一個人最多帶毬一次,如果帶了兩次,那麼從第一個位置移動到第二個位置的時候帶著毬一定更優,所以我們讓最近的人走過來。拆點 dijkstra 即可。
「JOI 2017 Final」繩
發現染色一定是開始的時候就染好,最後直接擰成最多兩個顏色。
經過手玩發現如果對於一個 01 序列,分成連續段,如果只有左右端點是奇數(偶數也可),中間部分是偶數那麼一定有解。
兩端長度大於 1 可以不斷自卷變成單個顏色,考慮歸納證明,比如左端是 \(1001\cdots\) 一定可以找到 0 的中點然後對摺,成功歸納。
正着也可以推,發現每次都是展開左端點或右端點,那麼左右端點一定變成偶數,展開的不完整段有可能變成奇數。
枚舉兩種顏色然後暴力做可以拿到 \(55 \%\)。
枚舉第一段是奇數還是偶數,剩下的部分發現全是偶數段,偶數段可以拆成兩個一對的,一對中的顏色肯定相同,對於顏色 x,y,它們省下來的代價就是 \(cnt_x+cnt_y-cnt_{(x,y)}\),\(cnt_{(x,y)}\) 是指相鄰兩個爲 \((x,y)\) 的個數。
實現時枚舉每種顏色,用桶記錄一下即可。
JOI 2018 Final
「JOI 2018 Final」糰子製作
對於一個糰子,只可能會有另外一個方向的糰子和它衝突,經過仔細觀察,發現衝突的糰子的 G 糰子都在一條對角線上,不在一條對角線的糰子一定不衝突,通過這個進行 dp 即可。
「JOI 2018 Final」月票購買
建出從 S 到 T 的可行最短路圖,一定是從 u 到達圖上,然後在從圖上的某個點走出,所以跑出 u, v 到別處的最短路,建出 s 到 t 的最短路圖(單向邊),拓撲排序之類的做即可。
「JOI 2018 Final」毒蛇越獄
一個題三種做法拼起來是我妹想到的!
可以根據 0 容斥,根據 1 容斥,暴力枚舉,複雜度分別是 \(\Theta(2^{cnt_0})\),\(\Theta(2^{cnt_1})\),\(\Theta(2^{cnt_?})\),發現 \(\min\{cnt_0,cnt_1,cnt_?\} \le 6\),找最小複雜度的做即可。
JOI 2019 Final
「JOI 2019 Final」有趣的家庭菜園 3
首先無解當且僅當最大顏色個數大於其他顏色個數之和 + 1,另外發現同顏色的不會交換,設大暴力 \(f[x][y][z][pre]\) 表示放了 x 盆 r,y 盆 g,z 盆 y 上一盆是 pre 的最少交換次數,枚舉下一個放啥就行了。
「JOI 2019 Final」硬幣收藏
如果 n 比較小的話可以二分圖帶權匹配,如果 y = 1 的話直接按 x 座標排序即可。這啓發我們先將棋子花費必須的代價將他們移動到合法範圍內 \(x \le n,y \le 2\)。
我們發現對於一條豎着的分界線來說,不會同時存在左邊的點穿到右邊去並且右邊的點穿到左邊來,也就是每條豎線都是單向傳遞的,這樣我們可以輕鬆算出每條豎線的貢獻,但是橫線不可以,因爲它的範圍太大了。
考慮類似均分紙牌式的貪心,從左掃到右,維護兩個變量 A,B,時時刻刻保證這兩個變量同號即可。
「JOI 2019 Final」獨特的城市
暴力怎麼做?對於每個點 dfs,找到其最長鏈,拿次長鏈將其覆即可,顯然不夠優,我們考慮優化這件事。
找出樹的直徑,每個點出發的最長鏈的端點一定是直徑的兩端點,所以以兩個端點做兩遍 dfs,算出最長鏈的端點爲其的答案。dfs 時先走長鏈,將短鏈暴力覆蓋上去,然後走短鏈,發現這樣一個性質,對於一條重邊鏈接的父親兒子 \((x,fa)\),fa 的輕邊需要覆蓋的長度 \(maxdep_{fa}\),有 \(maxdep_{fa}=maxdep_{x}+1\),所以修改一個位置即可。是一道非常巧妙的題。
本質上說:其他對於每個點都有一個需要覆蓋的區間,輕兒子需要刪除的區間恰好就是長鏈的長度,而這個是可以轉移過來的。
JOI 2020 Final
「JOI 2020 Final」奧運公交
考慮每條邊的貢獻,如果這條邊在 1 到 n 和 n 到 1 的最短路上,這樣的邊只有 \(\Theta(n)\) 個,可以直接暴力翻轉最短路做掉。
不經過它的 1 -> n 最短路和 n -> 1 最短路都已經求得,經過它的最短路就是強制從 1 到 x,然後從 x 到 n 的最短路,有可能會有衝突,但我們可以記錄一下次短路(不同前驅的),這樣就可以算出來了。
「JOI 2020 Final」火災
在會了。