即將退役選手還是簡單寫下題解
Day1
T1 卡牌游戲
據說有\(O(n)\)做法
先二分答案,然后枚舉最小值是來自A還是來自B
這樣我們需要反轉一段前綴以及一段后綴,處理個B的前后綴最大/小值就能判斷
從小往大枚舉可以雙指針做到\(O(n)\)check
時間復雜度\(O(nlogA_i)\)
T2 矩陣游戲
一道類似的題link
一道類似的題link
傳統的做法是枚舉矩陣的\(a_{11}\)然后設出每行和每列的第一個數差分約束建圖,或者是搜索
但是這道題好像做不了,原因是值域太大
我們考慮先確定一個不考慮值域限制的矩陣然后調整它
那么你的操作就是交替給每一行/列執行++--的操作
於是你會發現你的每一個格子也是一個形如\(L \leq a_i \pm b_j \leq R\)的形式
考慮反轉所有奇數的行和偶數的列
那么每個格子都可以變成\(L \leq a_i - b_j \leq R\)的形式
直接差分約束即可
juruo不會寫spfa導致T成傻子,學了dalao的寫法雙端隊列才過
認為\(n,m\)同階,時間復雜度\(O(n^3)\)
T3 圖函數
不難想到考慮每個點的貢獻
一個點\(u\)能對\(v \geq u\)產生貢獻當且僅當
\(u\)和編號比它大的點構成的導出子圖中\(u\)和\(v\)在同一個環上
於是就有一個每個點每張圖都跑一次tarjan的優秀做法
時間復雜度\(O(nm^2)\)
這個做法看起來沒法優化
我們考慮這其實只要求一個環而不需要知道SCC
於是我們考慮直接對每個點\(u\)考慮他能和\(v\)成環當且僅當
圖中存在一條\(u->v\)的路徑和\(v->u\)的路徑只經過編號\(\geq u\)的點
這好像是廢話
但是這樣就可以做了
考慮這條路徑的貢獻其實就是路徑上編號最小的邊,編號在這之前的圖都可以滿足條件
不難發現只需要對每個點dijkstra跑個最短路就可以計算貢獻
但是這樣看起來是\(O(nmlogm)\)的,貌似過不了
考慮一個更easy的想法
我們只需每次加入一個邊的時候擴展\(u\)所在的連通塊
這樣每個點/邊只需被加入一次
時間復雜度\(O(nm)\)
注意卡常
Day2
T1 寶石
樹上跳等差數列一類的東西不難想到倍增
預處理出\(f/g\)兩個倍增數組,表示每個點向上第一個點權是這個點點權的前驅/后繼的點
於是對於一個詢問\(s->t\)
\(s->lca\)的這段可以考慮用\(g\)直接\(O(logn)\)處理
\(lca->t\)的這段好像不好搞
只能先二分答案,然后用\(f\)從\(t\)跳上去判斷是否可行
這個是\(O(log^2n)\)的
我們發現不管是預處理倍增數組還是處理詢問都需要訪問一個點祖先上最近的某一種顏色的位置
不難想到把詢問離線,開一個桶在樹上掃3遍即可
時間復雜度\(O(nlogn+qlog^2n)\)
T2 滾榜
不難想到\(O(n!*n)\)的做法
即枚舉所有排列
那么可以掃一遍出\(b_i-b_{i-1}\)的最小值,做個前綴和判斷是否\(\leq m\)即可
考慮優化成狀壓dp
不難想到設狀態\(f[S][i][j][k]\)表示當前選了\(S\)中的點,最后一個是\(i\),當前最后一個\(b_i\)是\(j\),當前所有\(b\)的總和是\(k\)的方案總數
發現時間復雜度\(O(2^nn^2m^2)\)甚至跑不過階乘算法
不難想到\(j\)和\(k\)可以合在一起,考慮每一個差分即\(b_i-b_{i-1}\)的貢獻是獨立的
於是狀態簡化為\(f[S][i][j]\)表示當前選了\(S\)中的點,最后一個是\(i\),當前所有差分的貢獻總和是\(j\)的方案總數
時間復雜度\(O(2^nn^2m)\)
用計算器一算5e8,還有很多空狀態,用刷表dp跑得飛快
T3 支配
不難得到支配樹的\(O(nm)\)建法
即暴力算出每一個點支配哪些點
於是我們就得到了一個每次詢問重構支配樹的\(O(nmq)\)算法
考慮每次直接在支配樹上搞
我們發現加邊只會讓點的支配集減小
並且若一個點的支配集減小,那么它的子樹的支配集也會減小
於是不能難發現一個點,若它祖先的支配集都沒被改變,那么它的支配集里一定刪去了支配樹上它的父親
那么考慮加入\(x->y\)會影響哪些點\(u\),使它的支配集里刪去了它的父親,然后再dfs一遍即可算出答案
首先,\(y\)需要能夠不經過\(u\)支配樹上的父親而到達\(u\)
這個可以枚舉每個點,在反圖中刪去它的父親來預處理
其次,\(x\)和\(u\)的lca不能是\(u\)的父親
這一點只需判斷\(fa[u]\)是否支配\(x\)即可
於是我們就在\(O(nm)\)預處理,單次\(O(n)\)處理詢問的復雜度內解決了這個問題
總時間復雜度\(O(n(m+q))\)