SDOI2021正睿一輪集訓
Day 1
一、線段樹
定理:任何一個區間線上段樹上會劃成 \(O(logn)\) 個區間
P4868
二、樹狀陣列
考慮前驅,去掉所有右兒子
每個點維護 \([x-lowbit(x)+1,x]\) 的和
P4868另一種做法
POJ2155 二維樹狀陣列(一維擴二維即可)
三、動態開點線段樹
每次編號,每個節點多維護左兒子和右兒子編號
四、可持久化線段樹
維護所有歷史版本線段樹,每次修改都建一個新點
CF323C
五、線段樹合併
從根開始合併。可持久化就每次合併直接新開一個點即可。
一次合併複雜度是兩棵線段樹公共點個數。每次合併總結點個數會減去公共節點個數,複雜度會加上它,所以均攤複雜度O(logn)。
CF600E(可以DSU on TREE)
六、二維線段樹(可用KDT)
第一維 \([l_1,r_1]\),第二維 \([l_2,r_2]\),維護矩形\((l_1,r_1,l_2,r_2)\)。
七、李超樹
支援插入直線,求 \(x\) 處最大值
每個區間維護 \(mid\) 處取值最大的直線,考慮幾種情況分類討論,可以保證每一次都只會下放一條直線到最多一半區間。每個區間不一定是最值,最後單點查詢的時候比較從根到其路徑上 \(O(logn)\) 個直線的最優解。
加線段?李超樹合併?CF932F
八、分塊
兩邊暴力,中間整塊的維護,每次 \(O(B+n/B)\)。
HDU6756,不太會
九、莫隊
二維O(n(3/2)),三維O(n(5/3))。
學會如何調整塊大小!奇偶塊排序只會優化大概1/2常數。
CF86D板子
十、帶修莫隊
加一個指標記錄版本,三維莫隊即可。
P1903板子
十一、樹上莫隊
尤拉序:DFS時進入和離開節點時記錄節點編號形成的序列。
st_l到st_r上出現奇數次的點出現在路徑上(無祖先關係就再加LCA)。
P4074 樹上帶修莫隊板子
十二、平衡樹
1.Splay
通過旋轉使整棵樹深度均攤O(logn)。
2.fhqtreap
treap=tree(bst)+heap,滿足堆的性質。
fhqtreap通過分裂和合並維護。
需要修改或者查詢的時候,就分裂開,然後單獨搞,搞完之後再合併即可。每次分裂和合並都是期望O(logn)。
fhqtreap的可持久化就是修改新開一個點就行。可持久化之後就不能用修正值的堆性質了,需要用類似按秩合併的思想用概率合併。
十三、樹鏈剖分
1.輕重鏈剖分
重兒子是子樹大小最大的兒子。
十四、LCT(Link-Cut Tree)
平衡樹使用Splay可以做到均攤O(logn)。維護一個重鏈的森林。
access(x) 把它到根的邊都變為重邊。
makeroot
findroot
split
link
cut
LCT還可以維護子樹資訊。
十五、ETT(Euler Tour Tree)
用平衡樹維護每個點在尤拉序上的括號序列。比較好維護子樹資訊。
把邊改掉相當於對一個子樹在區間上平移。
十六、KDT
十七、綜合練習題
HDU5118,CF1149C,CF482E,CF1192B,P4764
Day 2
構造題專場??
T0熱身題:
偶數無解,左邊加起來n(n-1),右邊加起來n(n-1)/2,模n意義下不相等。
奇數直接取兩個一樣的從小到大排列即可。
T1三元環問題:
考慮上界,猜出一定有一個構造滿足上界。用異或性質一一對應來構造出一組方案。
T2完全圖邊分組:
對於(x,y),放在(x+y) mod (2n-1)這一組,然後對於每個k都取一個i,2k=i (mod (2n-1)。放在這一組。
T3完全圖構造生成樹:
歸納構造,考慮已經構造完2k的情況,考慮2k+1和2k+2的情況如何由2k的情況連幾條邊得到即可。
通過整除之類的性質先判斷上界!
T4平面內三角形:
隨機方向向量不與邊重合,考慮先構造一組方案,然後用凸包消去多餘的點,證明下界2n-2-凸包點數。
T5類魔方變換:
貪心,當前列需要k,那就從後面找個k花幾步放回來。構造交換任意兩個位置的方案即可。
T6序列大小位置相鄰:
劃分成n個段,每次選次小值最小的一個段,刪去整個段,其他段刪去比這個次小值小的數(最多一個),因此必然能選n次,必然有解。
T7向量和為零:不會
T8環上三個顏色:
找中間狀態,先考慮如何從中間狀態轉移。
T9變換:考慮構造一組操作把最大值放在右下角。
T10給uv的較大或較小值:
2-SAT問題,主要就是根據真假關係拆點建邊,然後找強連通分量即可。這個題維護一個上界下界,每個點選擇賦上下界一定不會更劣,轉化為2-SAT求解即可。
CF1375H 值域分塊或值域分治
CF1364E
CF1365G
CF1290D
CF1292E
CF1288F
CF1097E
CF1227G
Day 5
Test 1
A
不能把剩餘油量放到 \({dp}\) 方程裡,所以需要考慮貪心和 \({dp}\) 轉移,設兩個 \({dp}\) 陣列,\({dp_{i,j}}\)表示從i加滿到j,\({dp_{2\ j}}\)表示到j油量為零,僅會有這兩種情況。
考慮對於 \((i,j,k)\) 如何從dp_{i,j}和dp2_{j}轉移到dp_{j,k}和dp2_{k}。分別考慮四種情況轉移即可。
C
30pts:bitset優化LCS O(n^2/w)
dp(i,j)=max(dp(i-1,j,dp(i,j-1),dp(i-1,j-1)+(s[i]==t[j]));
考慮建成一個網格圖,求(a,c)與(b,d)最長路。具體做法:網格圖分治,取中間點,列舉怎麼通過中間分界線。
70pts:好像是預處理T(n)=T(n/2)+O(n1.5),總的O(n1.5)=O(|s|3),總的複雜度O(|s|3+q|s|)。橫豎接連著切保證邊界上的點是根號級別。
Day 3
ICPC 題目選講
2020 上海區域賽
L.Traveling in the grid world
Day 6
組合計數
熱身題1
有 \(n\) 堆石子,已知每堆石子的數量都介於 \([1,2^m-1]\) 之間且互不相同。給定 \(n,m\),每堆石子中的數量可以任選(但必須滿足上述要求),求有多少種方案可以使得 nim 遊戲下先手取勝。
算後手必勝(異或和為 \(0\)) 的情況。如果沒有非 \(0\) 和不相同的限制,答案就是 \((2^m-1)^{n-1}\),除最後一位以外都可以任選。非 \(0\) 的話,算 \(f_i\) 的時候減去 \(f(i-1)\) 即可。算相同的話,式子就是
\[f_i=\prod_{i=2^m-i+1}^{2^m-1}i-f_{i-1}-(2^m-1)(i-1)f_{i-2} \]複雜度 \(O(n)\)。
熱身題2
給出 \(n\) 個正整數 \(a_i\),你要選出 \(n\) 個正整數 \(b_i\) 和 \(n\) 個正整數 \(d_i\),對於每個 \(i\) 滿足 \(b_i|a_i\) 且 \(d_i|b_i\),求有多少種選法滿足 \(\prod d_i^2\geq \prod b_i\)。\(n\leq 100,a_i\leq 10^9\)。
首先注意到,\(\prod d_i^2>\prod b_i\) 與 \(\prod d_i^2<\prod b_i\) 是一一對應的,所以現在只需要計算 \(\prod d_i^2=\prod b_i\) 的方案數。對每個質因子跑一邊揹包應該就行了。複雜度 \(O(\sum a_i+(n\log a_i)^2)\)。
CF838D
一輪省集出過的 nb 題!
考慮合鏈成環,新加一個 \(n+1\) 號點佔位(不能被某個人佔領)。那麼每個點不被佔領的概率就是 \(\frac{n+1}{n+1-m}\),乘以 \(n+1\) 個位置的方案數 \(2^m(n+1)^m\) 即可。
CTSC2017 吉夫特
首先根據 Lucas 定理,選出來的子序列前面的數必須是後面的數的超集。然後這個東西可以直接列舉超集轉移,複雜度 \(O(3^{\log(\max a_i)})\)。這個東西還可以進行一個非常 nb 的優化:類似分塊,定義 \(f(u,v)\) 表示前 \(9\) 位為 \(u\),後 \(9\) 位為 \(v\) 的超集的 dp 值之和。這樣,計算當前位置的 dp 值的時候,只需要列舉當前 \(a_i\) 的前 \(9\) 位的超集,然後更新的時候只需要列舉後 \(9\) 位的超集。複雜度 \(O(2^9\cdot n)\)。
括號序列
求有多少個長度為 \(n\) 的括號序列滿足其所有子序列中最長合法括號子序列的長度恰好為 \(2k\),多組資料。\(T,n\leq 2\times 10^5\)。
令左括號為 \(+1\),右括號為 \(-1\)。設字首和陣列為 \(s_i\),那麼最長合法括號子序列的長度為 \(n-s_n+2\min s_i\)。證明大概說的是,考慮一下最少需要拿走多少個括號。從開頭開始,一旦當前左括號個數 \(<\) 右括號個數,那麼接下來的一段右括號就都不行了。這時候直接把起點放到接下來一段右括號後面然後繼續做。最後的時候,起點的高度已經變成 \(\min s_i\) 了,剩下 \(s_n-\min s_i\) 這麼多左括號沒辦法找到匹配的右括號。把這些不能匹配的左右括號扔掉之後,剩下的就能形成合法括號序列了,這個長度是 \(n-s_n+2\min s_i\)。
接下來我們考慮列舉 \(t\),那麼 \(s_n=n+2t-2k\),計算 \(\min s_i>t-1\) 和 \(\min s_i>t\) 的方案數相減得到 \(\min s_i=t\) 的方案數。計算 \(\min s_i>t-1\) 的話,相當於畫一個長度為 \(n\),高度從 \(0\) 到 \(s_n\) 的不經過 \(y=t-1\) 的折線。使用那什麼翻折引理,可以得到這個方案數等於沒有任何限制情況下到 \(s_n\) 方案數減去到 \(s_n\) 關於 \(y=t-1\) 對稱的位置的方案數(這個證明我想的是構造一個雙射,使得每一種不合法情況與後面這種的某種情況一一對應就行了)。
然後可以得到這個式子
\[\binom{n}{\frac{n-s_n}{2}}-\binom{n}{\frac{n-(2(t-1)-s_n)}{2}}=\binom{n}{k-t}-\binom{n}{n-k+1} \]同理可以得到 \(\min s_i>t\) 的方案數為
\[\binom{n}{k-t}-\binom{n}{k} \]然後一減,發現和 \(t\) 無關……考慮 \(t\) 的取值只需要滿足 \(s_n\geq t\),解得 \(-t\leq n-2k\)。又因為 \(-t\geq 0\),所以 \(t\) 有 \(n-2k+1\) 種取值,也就是說,答案為
\[(n-2k+1)\big(\binom{n}{k}-\binom{n}{k-1}\big) \]某道省選題
一棵樹,每條邊限制兩個端點的大小關係(限制 \(a_u>a_v\) 或 \(a_u<a_v\))。求有多少種符合要求的排列 \(a\) 滿足整棵樹的限制。\(n<=5000\)。
首先考慮一個簡單的問題:樹上所有邊的方向都向下。這種情況就等於樹上拓撲序計數,答案為 \(\frac{n!}{\prod siz_u}\)(證明大概說的是,考慮每個子樹根都必須是子樹內最大的,這個在全排列中的概率是 \(\frac{1}{siz}\))。然後我們考慮一個暴力:對於所有反向的邊,直接不予考慮,這樣樹上會形成若干個連通塊,算出這個答案之後,對所有反向邊進行一個容斥。接下來就要開始 nb 了:我們考慮一個 nb dp,設 \(f(i,j)\) 表示 \(i\) 為根的子樹,當前與 \(i\) 連通的連通塊大小為 \(j\) 的方案數。如果是一個正向邊直接合並,如果是反向邊,那麼有兩種合併方式(容斥,有一種要乘上 \(-1\) 的係數)。直接做這個樹揹包就行,複雜度 \(O(n^2)\)。
LOJ 575 不等關係
上邊那個題放到序列上,但是 \(n\leq 10^5\)。考慮還是上邊那個做法,但是你發現這個時候第二維顯得沒那麼重要了,乾脆只開一維,轉移為
\[g_i=\sum_{j=0}^{i-1}\frac{[s_j='>']}{(i-j)!}g(j)(-1)^{cnt_{i-1}-cnt_j} \]就是你列舉上一次的斷點在哪裡,這裡設 <
為正向,那就是找你欽定的上一次的 >
且是斷點的地方轉移。這個式子看起來很像卷積形式,直接分治 NTT 即可做到 \(O(n\log^2 n)\)。
一些關於 Matrix-tree 定理的半懂不懂的話
Matrix-Tree 定理的本質是對環容斥。正常容斥係數應該是 (-1)^環個數。Matrix-Tree 定理刪掉基爾霍夫矩陣中根所在的行列後,任意一個排列如果某一位選了它自己(即選在對角線上),那就說明從出邊中隨便選了一條;否則剩餘的部分會形成若干個環,如果這些環形成的是奇排列則會有 -1 的係數。奇排列就相當於環的總長度減掉環個數是奇數,由於非對角線元素都取了相反數,因此 \((-1)\) 被乘的次數恰好是環的總長度,再乘上奇排列的係數,恰好就是 (-1)^環個數。因此 Matrix-Tree 定理不僅可以用於無向圖,也很容易可以推廣到任意有向圖上。
某道題
給⼀張 \(n\) 個點 \(m\) 條有向帶權邊的有向圖。這張圖的⼀個樹形圖定義為:從 \(m\) 條邊中選出 \(n-1\) 條邊,使得所有點都可以通過這些邊走到 \(n\) 號點。 ⼀個樹形圖的權值定義為這 \(n-1\) 條邊的權值和。求出所有樹形圖的權值和,答案對 \(998244353\) 取模。\(n\leq 500\)。
一個經典的加轉乘做法是,把每條邊看作一個一次函式 \(wx+1\),你發現這裡的一次函式乘法(\(\bmod x^2\) 意義下)相當於在一次項係數上加!然後這題要注意,\(ax\) 不一定有逆元的(無常數項),如果遇到了一整列都沒有,這種情況下要對一整行都除以 \(x\),然後把答案乘以 \(x\),當然都是 \(\bmod x^2\) 意義下的。
然後這個題如果沒有考慮 \(ax\) 無逆元的情況,可以構造一個答案為 \(\bmod\) 的倍數的圖。也就引發出了一道構造題:構造一個有向圖,使得以 \(1\) 為根的生成樹個數恰好為 \(k\)。\(k\leq 10^{18}\)。
首先把 \(k\) 表示成 \(2^p-2^{a1}-2^{a2}-\ldots\) 這樣的,考慮先弄 \(p+1\) 個點,每個點 \(i\) 向 \(i-1\) 和 \(1\) 連邊,這樣生成樹個數就是 \(2^p\)(因為是 DAG)。然後對於某個 \(ai\),考慮把倒數 \(n-ai\) 位置的點到 \(1\) 的邊改成到末尾 \(p+1\) 的邊,這樣就形成一個環了,用對環容斥的方式可以得到答案為 \(k\)。
某道集訓題(正睿NOIP集訓Test16-C)
\(y\) 軸正半軸上有 \(n\) 個點 \((0,a_1),\ldots,(0,a_n)\),他們每次可以向右或向下走一格,求最後分別到 \((1,0),\ldots,(n,0)\) 的方案數。\(n,a_i<=10^6\)。
首先根據 LGV 引理可以得到答案是求:
\[\left|\begin{array}{cccc} \binom{a_1+1}{1}&\binom{a_1+2}{2}&\cdots&\binom{a_1+n}{n}\\ \binom{a_2+1}{1}&\binom{a_2+2}{2}&\cdots&\binom{a_2+n}{n}\\ \vdots&\vdots&\ddots&\vdots\\ \binom{a_n+1}{1}&\binom{a_n+2}{2}&\cdots&\binom{a_n+n}{n} \end{array}\right| \]提出公因子來可以得到
\[\frac{\prod (a_i+1)}{1!2!\cdots n!}\left|\begin{array}{cccc} 1&(a_1+2)^{\underline{1}}&\cdots&(a_1+n)^{\underline{n-1}}\\ 1&(a_2+2)^{\underline{1}}&\cdots&(a_2+n)^{\underline{n-1}}\\ \vdots&\vdots&\ddots&\vdots\\ 1&(a_n+2)^{\underline{1}}&\cdots&(a_n+n)^{\underline{n-1}} \end{array}\right| \]然後有一個結論說的是,任意的矩陣滿足 \(A_{i,j}\) 為 \(a_j\) 的 \(i-1\) 次多項式,都可以消元成以下形式:
\[\frac{\prod (a_i+1)}{1!2!\cdots n!}\left|\begin{array}{cccc} 1&a_1&\cdots&a_1^{n-1}\\ 1&a_2&\cdots&a_2^{n-1}\\ \vdots&\vdots&\ddots&\vdots\\ 1&a_n&\cdots&a_n^{n-1} \end{array}\right| \]然後這個東西叫做範特蒙德矩陣,行列式就是
\[\prod_{1\leq i<j\leq n}(a_j-a_i) \]令 \(g_j\) 表示 \(a_i=j\) 的 \(i\) 的數量,則原式可以寫成
\[\sum_{k}k\big(\sum_{j=k}^{10^6}g_j g_{j-k}\big) \]直接卷積即可。複雜度 \(O(V\log V)\)。
Day 7
圖論與網路流
一、強連通分量
-
強連通分量是一個極大強連通子圖。
-
忘了……
-
kosaraju演算法縮點:dfs求post-order(dfs回溯順序),然後邊反向、用post-order反序dfs,每一次搜到的點都在一個強連通分量裡面,這一次的順序就是DAG的拓撲序。然後建邊就掃描原圖中的點就行了。
例題:CF949C,根據條件建有向邊縮點求最小的出度為0的強聯通分量
二、2-SAT
- 把每個點分成真假兩個狀態。
- x->y:若要取x這個狀態,必須取y這個狀態。
- 如果x->非x,那麼無解。
- 最後就縮點然後看每個點的哪個狀態在強連通分量內即可。
- a是真:非a->a
例題:P5332,每一個人在每一個時間建一個點然後2-SAT建圖,如果最後的那個x能夠連向最後的非x,那麼忽略這個點。在另外的點中找出每個人真能夠連向的所有真。
三、歐拉回路
- 有一個巧妙的方法。
例題:CF1361C
四、割點與橋
- 定義dfn和low兩個陣列。
- 點雙聯通分量是用割頂相連的,邊雙聯通是用橋相連的。
- 求點雙聯通,找到割點,從棧中彈出來的點都在同一個點雙連通分量中。
- 同理,邊雙和橋一樣。
例題:LCT維護動態的邊雙聯通縮點樹,查詢樹上路徑和。LCT經典維護方案,套一個並查集(Father),然後每個點訪問到之後直接訪問它的find(x),如果這個點是根,那相當於這個點存在在LCT中,否則不存在。複雜度沒有問題。
五、圓方樹
- 仙人掌:任意一條邊至多隻在一個簡單環內。
- 狹義圓方樹求解仙人掌問題。把仙人掌轉化為圓方樹從而可以使用樹形dp等問題求解。
- 廣義圓方樹對於每一個圖中的點雙連通分量建立一個方點,把原圖中的點刪掉然後從每一個方點向它所對應的點雙中的點連邊。兩個性質。
例題:CF487E,圓方樹樹剖板子。
六、網路流
- 最大流Dinic兩個優化:當前弧和炸點
例題:CF1082G,基礎網路流最小割模型建圖。
-
dijk優化spfa的費用流,類似於Johnson。
-
zkw費用流就是在最短路徑上跑Dinic。
例題TOPCODER12432
-
無源匯上下界可行流
-
有源匯上下界最大流