LOJ3271「JOISC 2020 Day1」建築裝飾 4
有一個顯然的 \(O(n^2)\) 做法,然后用歸納法可以證明任意時刻合法的位置都是一個線段,就可以 \(O(n)\) 了。
要不是這題我才不會想到優化呢
LOJ3272「JOISC 2020 Day1」漢堡肉
考慮 \(\min R,\max L,\min U,\max D\) 這四個值。
如果 \(\min R\ge \max L\) 或 \(\min U \ge \max D\) 那么顯然可以退化到一維的情況。
否則,在 \(K \le 3\) 的時候,容易發現邊界的四個交點上至少有一個竹簽,否則無法把所有邊界覆蓋,所以可以枚舉插了哪個交點,刪掉覆蓋這個交點的矩形,然后遞歸。復雜度 \(O(4^Kn)\) 。
如果這樣搜索不出解,那么就只能是四個竹簽分別在四條邊界上,相當於是有四個變量。
對於一個矩形,如果和三個邊界有交,即完整地包含了一條邊界,那么顯然不需要考慮。
如果只和一個邊界有交,那么就是限制了某一個變量取值在某一個區間內。
如果和兩個邊界有交,那么就是限制 \(x_1\in [l1,r1]\ or\ x_2\in [l2,r2]\) 。
不妨設一個 01 變量表示是否有 \(x_1\in[l,r]\) ,那么這些限制就可以寫成 2-sat 的模型。
由於滿足的限制需要有解,所以如果 \([l1,r1]\cap [l2,r2]=\varnothing\) ,那么它們不能同時成立。容易發現,只要滿足這些條件,線段的交就一定有解。
於是前綴和優化建邊即可。
LOJ3273「JOISC 2020 Day1」掃除
先考慮沒有插入的時候怎么做。
對於被推過的灰塵,它們都會在一個形為折線的邊界上。
對於折線上的灰塵,滿足每次被操作的灰塵一定是一個區間,所以用平衡樹上二分即可找到坐標被區間賦值的一段。
而對於之前不在折線上的灰塵,可以提前算出它們在哪一次操作之后會被並入折線。
所以沒有插入的情況可以 \(O(q\log q)\) 解決。考慮如何處理插入。
對於一個詢問,相當於是問一個點經過一段區間的操作之后會到哪里。
用線段樹拆成 \(O(q\log q)\) 個這樣的詢問,放在若干個區間上。
那么此時對於線段樹上的一個區間,點集是固定的,就可以按照沒有插入的做法做了。
總點集是 \(O(q\log q)\) 的,而總操作次數也是 \(O(q\log q)\) 的,所以復雜度 \(O(q\log^2 q)\) 。
還有另外一種做法,感覺更好想一些?
這個等腰直角三角形看着比較不爽,所以用類似線段樹的拆分方法拆成 \(O(n\log n)\) 個矩形。雖然 \(n\) 很大但是子樹內沒有灰塵的矩形顯然沒有必要建出來。
那么可以發現,對於一次修改,只會影響到 \(O(\log n)\) 個矩形。
而修改對矩形內部造成的影響就是比較簡單的了:坐標取 \(\max\) ,或是把某一個范圍內的點全部踢到子樹內。可以用各種神奇數據結構維護。
因為深度是 \(O(\log n)\) 的,所以要踢出去的時候可以暴力一個一個處理。
LOJ3274「JOISC 2020 Day2」變色龍之戀
update:寫完才發現 \(C_{L_x}\ne C_x\) ,我人傻了……
請自覺忽略關於初始 \(deg=2\) 的所有討論。
考慮暴力枚舉兩個點,看它們在一起有幾種顏色。如果只有一種顏色那么連一條邊。
那么最后一個點連出去的邊會有三種:它喜歡的、喜歡它的、顏色相同的。(記為 1,2,3 類邊)
顯然 cp 關系會形成環,設一個點連向它喜歡的點的邊是它的出邊。
先假設所有點的度數都是 3 。
那么就可以對於每一個點,枚舉兩個相鄰的點和自己一起詢問,只有一種顏色當且僅當另外兩個點分別是喜歡它的和顏色相同的。由此可以確定它的出邊。
於是可以把所有環邊確定,就能確定顏色相同的點對。
然后考慮各種特殊情況。
- 1,2 不同,3 與 1,2 中的某一個相同,度數為 2 。
- 1,2 相同,3 與 1,2 不同,度數為 1 。
- 1,2,3 均相同,度數為 1 。
可以發現對於度數為 1 的點,它的 cp 也是度數為 1 ,並且它的同色點已經確定了。那么可以把這些點和它們連出去的邊刪掉。
此時一共只有三類點:
- 1,2,3 都不同且都存在,度數為 3 。
- 1,2 不同,3 被刪掉了,度數為 2 。
- 1,2 不同,3 與 1,2 中的某一個相同,度數為 2 。
並且我們可以知道每一個點是哪一種。
對於一二類點,它的(環上的)出邊在一開始就已經確定了,且出邊顯然不是重邊。
那么從一個出邊確定的點開始沿着出邊走,就可以得到一整個環的信息。
那么此時只有一種點的信息沒有確定了:一整個環都是三類點,環邊和重邊交替。
此時選連續的三個點 \(x,y,z\) ,若詢問結果為 1 則 \(y,z\) 同色,否則 \(x,y\) 同色。
那么就可以把所有關系都得出來了,就做完了。
然而這個圖還沒能建出來……
注意到這個圖是二分圖,所以必定可以把所有點分成兩個獨立集,獨立集中的點要么互不影響,要么是 \(L_{L_x}=x\) 的 cp ,但是后一種情況其實也是互不影響的。
那么依次加點,求這個點的所有邊,顯然可以在兩個獨立集內分別二分找邊。
於是詢問次數 \(O(n\log n)\) 。
LOJ3275「JOISC 2020 Day2」有趣的 Joitter 交友
前面的分析不是很難,但是感覺不是很會實現 /px
對於一個集合,維護 \(point\) 表示集合內的點的編號,\(ine\) 表示連入的點的編號, \(inp\) 表示連入的集合編號, \(outp\) 表示連出的集合編號。
合並的時候,先減掉分別的貢獻,合並完成后再加上一整個的貢獻。貢獻為 \(f(S)=|S|\times (|S|-1)+|S|\times |ine|\) 。
合並的時候按照 \(|S|\) 啟發式合並,容易發現這樣復雜度一定不會有問題。假設合並 \(x,y\) 之后的集合編號定為 \(y\) 。
先把 \(point\) 和 \(ine\) 無腦合並起來。
對於 \(v\in outp_x\) ,有 \(x\in inp_v\) ,需要改成 \(y\in inp_v\) 。\(v\in inp_x\) 同理。
對於 \(z\in (inp_x\cap outp_y+outp_x\cap inp_y)\) ,需要進一步合並 \(y,z\) ,把這些點對存在一個隊列里依次合並。
既然都啟發式合並了,所以入隊列的總點對自然應該也不會太多。
LOJ3276「JOISC 2020 Day2」遺跡
胡出正解了好激動
為了方便+能做,假設同一個數的兩個分身是不同的,最后再乘 \(2^{-n}\) 。
先考慮怎樣可以在不暴力模擬的情況下得到一個序列是否合法。
按照值域從大到小考慮,以 223311
為例。
先看到兩個 3 ,那么右邊那個保留下來,左邊那個會變成 2 ;
然后有三個 2 ,仍然保留最右邊的 2 ,其它 2 或早或晚都會變成 1 。
最后有四個 1 ,保留最右邊的 1 。
然而這樣還是不太好計數。
轉換成從右往左考慮,維護 \(vis_x\) 表示數 \(x\) 是否有被定下來位置。加入一個數 \(y\) 的時候 while (vis[y]) --y;
,即可知道它會變成什么,或是被刪掉。
但是顯然 DP 的時候也還是不能把 \(vis\) 存下來。
注意到我們最主要關心的是 \(vis\) 的極長前綴 1 的長度,所以不妨只記這個東西。
那么當前位置要被刪掉的時候就可以轉移了,而如果當前位置要被加入的話,就枚舉加入之后極長前綴 1 的長度會變成什么,計算貢獻。
https://www.cnblogs.com/dysyn1314/p/12877113.html 神仙dy的博客講得更加詳細。
LOJ3277「JOISC 2020 Day3」星座 3
我也忘記怎么做了……建出笛卡爾樹之后線段樹合並亂搞一通好像就行了。
https://loj.ac/submission/772893
LOJ3278「JOISC 2020 Day3」收獲
想到思路不難,不過實現也有一些細節。
顯然果樹之間兩兩獨立,而一棵果樹被某個人摘了之后下一次被摘顯然是這個人往后第一個距離超過 \(C\) 的人。這樣連一條邊即可連出一個基環內向樹。
對於樹上的情況,相當於詢問子樹內某個權值小於等於某個數的果樹個數,隨便做。
對於環,可以先把環上的一條邊斷掉,算出不經過這條邊的貢獻,然后把所有果樹都移到這條邊指向的點。
此時的詢問就可以被看做一個二維數點(走過來的時間不能太長,然后按照模環長的余數分類),離線一下即可 \(O(n\log n)\) 。
https://www.cnblogs.com/dysyn1314/p/12582983.html 神仙dy的博客講得更加詳細。
UOJ509. 【JOISC2020】迷路的貓
關於LOJ,它咕了
竟然又直接搞出正解了,爽啦
對於 \(A\ge 3\) 的情況,有這么一種構造方法:
把 BFS 樹建出來,那么我們想要每個點每一步都能使得 \(dep=dep-1\) 。
既然有三種顏色,那么可以搞出這么一種大小關系: \(0<1,1<2,2<0\) ,然后對於每個點,把能走的標成一種顏色,不能走的標成比它大的一種顏色。
其實就是把顏色標為 \(dep_x\%3\) 。
然后只考慮 \(A=2,m=n-1,B\ge 6\) 。
如果每一個點的兒子數量都不是 1 ,那么容易發現只需要按深度黑白染色即可。
所以考慮鏈應該怎么做。
把鏈上的邊循環染色,一個循環節為 BBWBWW
。
盯着這個串 BBWBWWBBWBWWBBWBWWBBWBWW...
如果起始點旁邊是 WW
或 BB
,那么沿着某一個方向連走兩步,就可以確定哪一邊是根的方向了。
否則,先往 B
走一步。如果此時走到了 BB
那么同樣按照上面的方法就可以知道哪一邊是根了。
否則再往同樣的方向走一步,那么可能走到 WW
或 BW
,也就知道哪邊是根了。
知道哪邊是根之后就很好搞定了,不走回頭路即可。此時多走的步數恰好最多為 6 。
怎樣套回到一棵樹上呢?
設根(即終點)是 \(x\) ,那么顯然根的每一棵子樹的染色方案互不影響,設某一個兒子是 \(y\) 。
如果之前沒有定下來 \((x,y)\) 的顏色,那么不妨欽定它是 B
。以下都假設 \((x,y)\) 是 B
,如果是 W
就把循環節循環移位一下變成 WWBBWB
,顯然前面的討論是不變的。
考慮 \(y\) 有幾個兒子:如果有超過 1 個,那么把這些邊全都變成 W
,然后發現只要能走到 \(y\) 就可以走到 \(x\) ,所以可以遞歸 \(x=y,y=son\) 。
否則,設 \(y\) 往下第一個不止一個兒子的點是 \(z\) ,那么把 \(x\to z\) 這一段按照鏈的方法染色,\((z,son_z)\) 的顏色設為 \((fa_z,z)\oplus 1\) ,然后遞歸。
分析一下正確性:如果出生點是 \(z\) 或是 \(z\) 的子樹,那么直接可以往鏈上走,然后不走回頭路一路走到 \(x\) ,且沒有多余步數;否則如果出生在鏈上,就可以按照鏈的做法做,同樣能找到 \(x\) 。
顯然如果鏈不夠長,在走鏈的過程中一不小心走到了 \(x\) 或 \(z\) ,那么也可以直接確定根的方向。
於是做完了。
LOJ3280「JOISC 2020 Day4」首都城市
不能想太多,暴力一點就贏了……
考慮建圖: \(x\to y\) 當且僅當 \(x\) 城市的小鎮組成的虛樹中包含 \(y\) 城市的小鎮。那么縮點之后就是出度為 0 的強連通分量大小的 \(\min\) 。
這個建圖用倍增優化即可。
LOJ3281「JOISC 2020 Day4」傳奇團子師傅
一開始胡了個二分圖匹配,然后發現白色可能會被用多次,然后就自閉了……
亂搞即可。不想學了。
LOJ3282「JOISC 2020 Day4」治療計划
想象一下按照時間順序模擬的情況:會有若干個健康區間,每次加入區間的時候可能會合並,然后隨着時間往后推左右端點往里縮。
然后……感受一下就可以得到這么一個做法:不再按時間模擬,而是從左往右加區間,最后要把區間連成 \([1,n]\) 。
兩個區間可以並在一起當且僅當 \(r_i+1\ge l_j+|t_i-t_j|\) 。
然后類似最短路轉移。令邊權為指向的點的點權。
為了優化最短路的過程,把絕對值拆開,把點按 \(t_i\) 排序,然后用兩棵線段樹分別維護區間中 \(l_j\pm t_j\) 的最小值和取到最小值的位置,轉移的時候把一整個前綴中合法的點都轉移掉,並在線段樹中刪除。
一個點只會被轉移一次、刪一次,所以復雜度 \(O(n\log n)\) 。