一些算法(套路)


目錄

容易被忽略的東西

分塊

二分答案

打表

差分

線段樹優化DP

差分約束

  如果只有 \(a_i\leq a_j+d\) 的約束,就可以直接上差分約束。

  如果有 \(a_i+a_j\leq d\) 的約束,考慮整張圖黑白染色,使得同色點之間只有差的約束,異色點之間只有和的約束,然后把白色的點的值取反,就可以跑差分約束了。

矩陣快速冪

  觀察一下矩陣是否是循環矩陣,如果是就可以用FFT解決(循環卷積)。

用BM算法優化矩陣快速冪DP

  記 \(B\) 為轉移矩陣。

  那么 \(B\) 中每個元素都對應着同一個常系數線性遞推關系。

  證明:

  記 \(B\) 的特征多項式為 \(f(x)=a_0x^k+a_1x^{k-1}+\cdots+a_kx^0\),那么就有

\[\begin{align} (a_0B^k+a_1B^{k-1}+\cdots+a_kB^0)&=0\\ B^t(a_0B^k+a_1B^{k-1}+\cdots+a_kB^0)&=0\\ a_0B^{k+t}&=-a_1B^{k-1+t}-a_2B^{k-2+t}-\cdots-a_kB^t\\ \end{align} \]

  這樣就可以求出前面 \(O(k)\) 項然后 \(O(k^2)\) BM一下得到遞推式再用倍增取模在 \(O(k^2\log n)\)\(O(k\log k\log n)\) 內求出任意項的值了。

  如果要求整個矩陣的遞推式的話,要拿這個矩陣哈希得到的值去BM,因為單項的最短遞推式可能不是整個矩陣的最短遞推式。
 

矩陣快速冪+DFT

  DP轉移如下:

\[f_{i+1,j',k+v}+=f_{i,j,k} \]

  \(i\leq n,j\leq l,k\leq m\)
  其中\(v\)只與\(j\)有關,最后求\(k=s\)\(k\bmod m=s\)的值的和。
  暴力搞的時間復雜度是\(O(l^3m^3\log n)\)的。
  我們可以把這個東西看成一個多項式。

\[g_{i,j}=\sum_{k\geq 0}f_{i,j,k}x^k \]

  
  轉移就可以看成乘以一個多項式(單項式)。
  如果求的是\(k\mod m=s\)的值的和,就可以看成循環卷積。
  可以先求值,把每個點值拿去跑一遍矩陣快速冪,再插值回來。
  時間復雜度:\(O(ml^3\log n)+\)點值插值的時間復雜度\(O(m^2)/O(m\log m)\)

多組詢問的矩陣快速冪優化DP

  設矩陣大小為\(m\),次數是\(n\),詢問組數是\(t\),朴素的實現是\(O(tm^3\log n)\)的。
  可以先把轉移矩陣的\(i\)次冪求出來。
  每次詢問只需要拿一個\(1\times m\)的矩陣去乘轉移矩陣就行了。每次乘法是\(O(m^2)\)的。
  時間復雜度:\(O(m^3\log n+tm^2\log n)\)

帶刪除的線性基

  對於線性基中的每個向量和所有 \(0\) 向量維護這個向量是由哪些向量異或得到的。

  在刪除一個向量 \(x\) 時,找到一個包含 \(x\)\(0\) 向量,如果沒有就找線性基里位最低的包含 \(x\) 的向量,把這個向量的信息異或到其他包含 \(x\) 的向量的信息中即可。這樣在刪除時不會影響線性基中更高位的向量。

  在向量個數比較小或強制在線是比較有用。

排序

  有些題如果把權值(或者其他東西)從小到大排序按順序做,會有出人意料的效果。

定期重構

  就每做 \(O(\sqrt q)\) 個修改就重構一下,每次詢問在建好的數據結構上查詢,還要把剩下的 \(O(\sqrt q)\) 的修改的影響一起算進去。

概率/期望DP

  有一些概率/期望DP可以快速地推出這樣的式子:

\[\begin{align} f_i&=a+bf_i\\ (1-b)f_i&=a\\ f_i&=\frac{a}{1-b} \end{align} \]

  BZOJ4872

  XSY2472

分治

  有一些問題求得是只包含/不包含一個點的情況,只需要考慮當前\([l,r]\)\([l,mid]\)\([mid+1,r]\)的影響。

  下面來講一道例題

  \(A(x)\)\(n-1\)次多項式,\(B_i(x)\)為一次多項式,\(\forall i\)\(A(x)\mod B_i(x)\)

  直接做是\(O(n^2)\)的。

  因為\((A(x)\mod C(x))\mod B_i(x)=A(x)\mod B_i(x)\)\(C(x)\mod B_i(x)=0\)

  設當前已經求出了

\[D_{l,r}=A(x)\mod(\prod_{i=l}^rB_i(x)) \]

  那么

\[\begin{align} D_{l,mid}&=D_{l,r}\mod(\prod_{i=l}^{mid}B_i(x))\\ D_{mid+1,r}&=D_{l,r}\mod(\prod_{i=mid+1}^{r}B_i(x)) \end{align} \]

  所以我們可以遞歸下去做,直到求出所有的\(D_{i,i}\)

  時間復雜度:

\[T(n)=2T(\frac{n}{2})+O(n\log n)=O(n\log^2n) \]

  多點求值

  XSY2469

歐拉phi函數

  就是\(\varphi\)函數

  誰都知道這個東西是個積性函數。

\[\varphi(ab)=\varphi(a)\varphi(b)~~~((a,b)=1) \]

  那如果\((a,b)\neq 1\)呢?

  設\(d=(a,b)\)

\[\begin{align} \varphi(a)&=a(1-\frac{1}{p1_1})(1-\frac{1}{p1_2})\cdots(1-\frac{1}{p1_{n1}})\\ \varphi(b)&=b(1-\frac{1}{p2_1})(1-\frac{1}{p2_2})\cdots(1-\frac{1}{p2_{n2}})\\ \varphi(ab)&=ab(1-\frac{1}{p3_1})(1-\frac{1}{p3_2})\cdots(1-\frac{1}{p3_{n3}})\\ \varphi(d)&=d(1-\frac{1}{p4_1})(1-\frac{1}{p4_2})\cdots(1-\frac{1}{p4_{n4}}) \end{align} \]

  可以發現,對於后面那部分

\[\begin{align} (1-\frac{1}{p1_1})(1-\frac{1}{p1_2})\cdots(1-\frac{1}{p1_{n1}})\times (1-\frac{1}{p2_1})(1-\frac{1}{p2_2})\cdots(1-\frac{1}{p2_{n2}})\\ =(1-\frac{1}{p3_1})(1-\frac{1}{p3_2})\cdots(1-\frac{1}{p3_{n3}})\times (1-\frac{1}{p4_1})(1-\frac{1}{p4_2})\cdots(1-\frac{1}{p4_{n4}}) \end{align} \]

  如果\(p\)只在\(a\)\(b\)中出現過,那么只會在\(ab\)中出現。如果同時在\(a\)\(b\)中出現過,那么會同時在\(ab\)\(d\)中出現。

  所以有

\[\varphi(ab)=\frac{\varphi(a)\varphi(b)d}{\varphi(d)}~~~(d=(a,b)) \]

逆向思維

情況一

  有時候我們做某個操作很不好做,我們可以先把所有操作做完后在一個個回復。

  例如:給以一個圖,有兩種操作:1.刪邊;2.詢問連通性。

  我們可以先把需要刪的邊刪掉,再一個個加回來,用並查集維護連通性。

情況二

  有時候問你\(\forall A\),滿足要求的\(B\)的和。

  我們可以枚舉所有的\(B\),計算每個\(B\)對每個\(A\)的貢獻。

  AGC005F
 

一類全序問題

  有\(n\)個物品,你要依次選擇這些物品,每個物品有三個屬性\(a_i,b_i,c_i\),當你選擇一個物品后,設當前選擇的物品的\(c\)屬性的和為\(s\),那么選擇這個物品的收益是\(a_i+b_is\),問你最大收益是多少。

  假設我們已經欽定了一個順序。考慮兩個相鄰的物品(不妨設為前兩個),什么時候當前順序比交換后更優:

\[\begin{align} a_1+a_2+b_2c_1&>a_2+a_1+b_1c_2\\ b_2c_1&>b_1c_2\\ \frac{c_1}{b_1}&>\frac{c_2}{b_2} \end{align} \]

  這樣我們就得到了一個全序關系。

  那么能不能擴展到任意兩個物品的情況呢?

\[\begin{align} a_i+b_ix+a_j+b_j(x+y+c_i)&>a_j+b_jx+a_i+b_i(x+y+c_j)\\ b_jy+b_jc_i&>b_iy+b_ic_j\\ \frac{c_i+y}{b_i}&>\frac{c_j+y}{b_j}\\ \end{align} \]

  好像並不太行。我們需要換一種思路。

  假設我們找到了一種最優解,但並不滿足以上的性質,那么一定可以交換相鄰兩個物品使得答案最優。所以直接排序貪心可以得到最優解。

  如果題目還有其他限制,你也可以在得到這個順序后DP或者干其他事情。

一類貪心問題

  有 \(n\) 個怪,組成了一棵樹。

  打一個怪會先扣 \(a_i\) 滴血,在加 \(b_i\) 滴血。

  怪的父親要在這個怪之前打。

  問你初始時最少要有多少血才能把這個怪打完。

  先不考慮父親比兒子早選的限制,把所有怪排序。

  考慮第一個怪,如果可以直接打,就直接打完。

  否則這個怪會在打完父親之后立刻打死,就把這個點和父親合並。

  題解

  HDU6326

  如果要對每個子樹求答案的話,可以用平衡樹維護操作序列,自底向上合並所有點的操作序列。

  【集訓隊作業2018】三角形

莫隊

  總所周知,莫隊的時間復雜度和塊大小有關。

  如果塊大小為\(t\),時間復雜度為\(O(\frac{n^2}{t}+mt)\)

  如果塊大小為\(\sqrt n\),時間復雜度為\(O((n+m)\sqrt n)\)

  如果塊大小為\(\frac{n}{\sqrt{m}}\),時間復雜度為\(O(n\sqrt m)\)

  所以有時候可以通過調整塊大小來加速。俗稱調參。

一類單點修改區間求和的問題

  有時候我們要修改一個點,求區間和。

算法 修改 求和
樹狀數組/線段樹 \(O(\log n)\) \(O(\log n)\)
分塊1 \(O(1)\) \(O(\sqrt n)\)
分塊2 \(O(\sqrt n)\) \(O(1)\)

  樹狀數組/線段樹的做法很經典,這里就不講了。

  分塊1:每次修改把對應的位置和對應的塊的和\(+1\)

  分塊2:每次修改把對應的位置和對應的塊的和\(+1\),然后求出塊內前綴和、塊內后綴和、塊的前綴和。

  有的人就要問了,分塊做法那么慢,有什么用呢?

  用處大着呢!當修改次數與詢問次數不平衡的時候,我們可以做到比樹狀數組更優。

  博主曾經用莫隊+分塊1水過了一道\(n=m={10}^6\)的題。跑的比zjt神犇的線段樹合並還快。

和排列有關的問題

  很多問題讓你求對於每一個排列\(A\),如果\(\cdots\),那么\(\cdots\)

  我們可以考慮從小到大插入這\(n\)個數,插入第\(i\)個數時考慮這個數的貢獻。

用trie實現全部數\(+1\),查詢全部數的異或和

  我們從低位到高位建一棵trie樹。

  從根開始,交換左右子樹,然后對\(0\)的那棵子樹執行同樣的操作(進位)。

莫比烏斯反演

  有很多題推着推着就推到\(\varphi\)上面去了。

  說明可以用一條式子:\(\sum_{d|n}\varphi(d)=n\)

莫比烏斯反演的多組詢問

\[\begin{align} ans&=\sum_{i=1}^lc^{\gcd(i,b)}\\ &=\sum_{d|s}c^d\sum_{i=1}^l[\gcd(i,s)=d]\\ &=\sum_{d|s}c^d\sum_{i=1}^{\frac{l}{d}}[\gcd(i,\frac{s}{d})=1]\\ &=\sum_{d|s}c^d\sum_{i|\frac{s}{d}}\mu(i)\lfloor\frac{l}{id}\rfloor\\ \end{align} \]

  看起來沒辦法化簡了

  這時候要枚舉\(j=id\)

\[\begin{align} ans&=\sum_{j|s}\lfloor\frac{l}{j}\rfloor\sum_{i|j}\mu(i)c^\frac{j}{i}\\ \end{align} \]

  設\(f(x)=\sum_{i|x}\mu(i)c^\frac{x}{i}\)

  這樣\(f(x)\)就可以預處理出來了。
  

一般情況

\[\begin{align} ans&=\sum_{i=1}^n\sum_{j=1}^mf(\gcd(i,j))\\ &=\sum_{i=1}^{\min(n,m)}f(i)\sum_{i|j}\mu(\frac{j}{i})\lfloor\frac{n}{j}\rfloor\lfloor\frac{m}{j}\rfloor\\ &=\sum_{i=1}^{\min(n,m)}\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{i}\rfloor\sum_{j|i}f(j)\mu(\frac{i}{j}) \end{align} \]

  這樣可以預處理后面的\(g(n)=\sum_{i|n}\mu(\frac{n}{i})f(i)\)
  每次枚舉前面詢問。
  時間復雜度:\(O(n+T\sqrt{n})\)  

分治FFT

  分治FFT一般有兩個用途。

求很多個多項式的乘積(普通分治)

  設有\(n\)個多項式,次數之和是\(m\),那么時間復雜度就是\(O(m\log m\log n)\)。一共有\(\log n\)層,每層是\(O(m\log m)\)的。

求一類數列(CDQ分治)

  數列\(f_n=\sum_{i=0}^{n-1}f_ig_{n-i}\)。對於一個分治區間\([l,r]\),先求出\([l,mid]\)的答案,再計算這部分對右邊\([mid+1,r]\)的貢獻。

  時間復雜度:\(O(n\log^2 n)\)

組合數學

\[\sum_{i=j}^{n-k}\binom{i}{j}\binom{n-i}{k}=\binom{n+1}{j+k+1} \]

  可以用插板法理解。

樹上的連通塊

  樹上連通塊個數\(=\)點數\(-\)邊數。

  點數/邊數中一般有一個是固定的。

輕重鏈剖分&長鏈剖分

輕重鏈剖分

  每個重鏈頂端的子樹大小總和是 \(O(n\log n)\) 的。

  每個點到根經過的輕邊個數是 \(O(\log n)\) 的。

  適用於維護與樹的大小有關的信息。

長鏈剖分

  每個長鏈頂端的子樹深度總和是 \(O(n)\) 的。

  適用於維護與樹的深度有關的信息。

高維前綴和 & 莫比烏斯反演

  復雜度為 \(O(\sum_{i}\frac{n}{p_i})=O(n\log log n)\)

\[g(n)=\sum_{d\mid n}f(d) \]

for(int i=1;i<=cnt;i++)
    for(int j=1;j*pri[i]<=n;j++)
        f[j*pri[i]]+=f[j];

\[g(n)=\sum_{n\mid d}f(d) \]

for(int i=1;i<=cnt;i++)
    for(int j=n/pri[i];j>=0;j--)
        f[j]+=f[j*pri[i]];

\[g(n)=\sum_{d\mid n}f(d)\mu(\frac{n}{d}) \]

for(int i=1;i<=cnt;i++)
    for(int j=n/pri[i];j>=0;j--)
        f[j*pri[i]]-=f[j];

\[g(n)=\sum_{n\mid d}f(d)\mu(\frac{d}{n}) \]

for(int i=1;i<=cnt;i++)
    for(int j=1;j*pri[i]<=n;j++)
        f[j]-=f[j*pri[i]];

網絡流

  如果要的是最大收益,那么可以先強制選所有正的邊,然后把不選一條邊看成割掉這條邊,答案為正的邊權和 \(-\) 最小割。

流量平衡

  可以先對於每條邊欽定一個方向,然后如果一條邊有流量就表示這條邊改了方向。對於一個點 \(i\),要根據出度入度的關系向源/匯連邊。

網格圖

  把每一行看做一個點,把每一列看做一個點,選一個格子就在對應的行列之間連邊。

  這是一個分層圖,用 dinic 跑會比較快。

一種限制

  每個物品對應一條鏈,割一條邊代表這個物品對應的數/放在什么位置。

  \(i\) 對應的鏈割了點 \(x\) 后面的邊時 \(j\) 對應的鏈必須割點 \(y\) 后面的邊

  解決方法為連邊 \((x,y,\infty)\)

  

  有時候限制是 \(i\) 割了點 \(x\) 后面的邊時 \(j\) 必須割點 \(y\) 前面的邊

  那么就要把一邊的鏈反過來。

  常見的方法有:

   橫着的鏈不變,豎着的鏈反過來。

   黑白染色,白色的點對應的鏈不變,黑色的點對應的鏈反過來。

  要注意前面的點屬於 T 集且后面的點屬於 S 集的情況。

  要從后面的點往前面的點連容量為 \(\infty\) 的邊。

  BZOJ3144切糕

原圖中不能有 \(S\to T\to S\) 的路徑

  把所有反向邊的容量設為 \(\infty\) 即可。

點分樹

  二叉樹的點分樹中每個節點只有至多 \(3\) 個兒子。這樣可以直接可持久化這棵點分樹,可以減少一個 \(\log\)(把點分樹當成三叉數可持久化,深度是 \(\log\) 的)。

  如果題目給的樹不是二叉樹,可以強行轉成二叉樹。

最小樹形圖

  用可合並堆維護每個點的最小入邊,可以做到 \(O(n+m)\log m\)

容斥方法 總結

每次在剩下的物品中選一種拿走一個,求拿走的最后一個物品是第一種物品的概率 的問題

  考慮容斥,枚舉哪些物品是在第一種物品拿完之后拿走的(剩下的隨意)。

  那么剩下的物品就可以忽略了,只需要求出第一種物品是第一個拿完的概率。

  對於 【UNR #3】百鴿籠 這道題,可以DP

   考慮拿走第一種物品時每種物品拿了幾個,就可以DP了:

   設 \(f_{i,j,k}\) 表示考慮完了前 \(i\) 種物品,有 \(j\) 種要在第一種取完之后才取完,已經取了 \(k\) 個物品。

   最終長度為 \(l\) ,取了 \(j\) 種的序列的序列的貢獻是 方案數 \(\times {(-1)}^j\times {(\frac{1}{j+1})}^l\)

  對於 【PKUWC2018】獵人殺 這道題,第一種物品是第一個取完的概率是 \(\frac{w_1}{\sum w_i}\)。可以用分治 NTT 計算方案數。

\(m\) 種顏色的球排成一行,共 \(n\) 個,求最終有 \(k\) 個同色的球相鄰的方案數

  先假設每種球分成幾段,然后用分治 FFT 算出方案數。

  但是這樣可能會有相鄰且同色的段

  這時候就可以容斥了。

  考慮每種方案把相鄰且同色的段合並之后有幾段

  那么就有

\[\begin{align} ans_i&=g_i−\sum{j<i}ans_{j}\binom{m−j}{i−j}\\ &=\sum_{j\leq i}g_j{(-1)}^{i-j} \end{align} \]

  https://www.cnblogs.com/ywwyww/p/8513349.html

\(m\) 種顏色的球排成一行,共 \(n\) 個,最終貢獻和同色段長度有關的

  先算出每種長度的貢獻

  假設想分成 \(i\) 段,但最終分成了 \(j\) 段,那么此時的容斥系數是 \({(-1)}^{i-j}\),方案數是 \(\binom{i-1}{j-1}\)

  然后拿最終分成的段數去跑 DP 就好了。

  https://www.cnblogs.com/ywwyww/p/9279670.html

和樹上兩點間路徑長度有關的技術&其他問題

  比如說樹上長度不超過 \(k\) 的路徑數量 等等

  現在主要有三種方法:

點分治/點分治樹

平衡樹合並/線段樹合並

長鏈剖分

  這里講幾道題吧

問題\算法 點分治 平衡樹合並 長鏈剖分
樹上長度不超過 \(k\) 的路徑條數(無邊權) \(O(n\log n)\) \(O(n\log n)\) \(O(n)\)
LOJ571 \(O(n\log^2n)\) \(O(n\log^2n)\) \(O(n\log n)\)
[WC2010]重建計划 \(O(n\log n\log V)\) \(O(n\log n\log V)\) \(O(n\log V)\)

ZKW 費用流中處理掉負權的方法

  先用 SPFA 跑一邊最短路,處理出 \(S\) 到每個點的距離 \(d_i\)

  顯然對於每一條邊 \((u,v,w)\) 都有 \(d_u+w\geq d_v\)

  對於一條邊 \((u,v,w)\),把這條邊的邊權變為 \(w'=w+d_u-d_v\)。這樣整個圖中就沒有負權了。

  容易證明在新圖上跑出的最短路就是原圖的最短路,只是長度有一點變化:\(d'_T=0\)

  所以后面原點到匯點的距離要加上 \(d_T\)

用 dijkstra 代替 bellman-ford 跑費用流

  還是先處理出 \(S\) 到每個點的距離 \(d_i\)

  還是把每條邊的邊權變為 \(w'=w+d_u-d_v\)

  因為新建的反向邊一定滿足 \(d_u+w_{u,v}=d_v\),所以 \(w_{v,u}'=-w_{u,v}+d_v-d_u=0\)

  新圖的最短路還是比原圖的最短路少了 \(d_T\)

單位根反演(求和引理)

  在碰到

\[\sum_{i=0}^n\binom{n}{i}a^ib^{n-i}[k\mid i] \]

  時可以用求和引理優化:

\[\begin{align} [k\mid i]&=\frac{1}{k}\sum_{j=0}^{k-1}w_k^{ij}\\ &~~~~\sum_{i=0}^n\binom{n}{i}a^ib^{n-i}[k\mid i]\\ &=\sum_{i=0}^n\binom{n}{i}a^ib^{n-i}\frac{1}{k}\sum_{j=0}^{k-1}w_k^{ij}\\ &=\frac{1}{k}\sum_{j=0}^{k-1}\sum_{i=0}^n\binom{n}{i}a^ib^{n-i}w_k^{ij}\\ &=\frac{1}{k}\sum_{j=0}^{k-1}{(aw_k^j+b)}^n \end{align} \]

prufer 序列

  \(K_{n,m}\) 的生成樹個數是 \(n^{m-1}m^{n-1}\)

  \(K_{n_1,n_2,\ldots,n_k}\) 的生成樹個數是 \(n^{k-2}\prod_{i=1}^k{(n-n_i)}^{n_i-1}\),其中 \(n=\sum_{i=1}^kn_i\)

  有一個 \(n\) 個點,\(m\) 個連通塊,每個連通塊大小為 \(a_i\) 的森林。你要加上若干條邊,讓這個森林變成一棵樹。方案數為

\[\sum_{\sum_{i=1}^m d_i=2(m-1)}(m-2)!\prod_{i=1}^m\frac{a_i^{d_i}}{(d_i-1)!}\\ =n^{m-2}\prod_{i=1}^ma_i \]

樹形DP

  \(f_{i,j}\) 為以 \(i\) 為根的子樹,選出來的點數為 \(j\) 時的方案數/貢獻。這里 \(j\leq k\)

  轉移時要枚舉兩邊各選了多少點。直接做是 \(O(nk^2)\) 的。

  注意到當選的點數 \(\leq size\) 時才有意義。這樣轉移時兩棵子樹選的點數可以只枚舉到 \(\min(size,k)\),這樣就是 \(O(nk)\) 的了。

  證明:
   1.兩棵子樹大小都 \(>k\)。只有 \(O(\frac{n}{k})\) 次轉移,復雜度為 \(O(\frac{n}{k}\times k^2)=O(nk)\)
   2.一棵子樹大小 \(\leq k\),另一顆子樹大小 \(>k\)。對於所有的這類轉移,小的那棵子樹的大小之和是 \(O(n)\) 的。復雜度為 \(O(n\times k)=O(nk)\)
   3.兩棵子樹大小都 \(\leq k\)。把所有這類轉移在樹上標出來,那么會標出很多棵子樹。每棵子樹復雜度為 \(O({size}^2)\),其中 \(size\leq 2k\)。復雜度為 \(O(nk)\)

  這樣總的復雜度就是 \(O(nk)\) 了。

用全局平衡二叉樹優化鏈剖+NTT

  如果 \(f_x\) 的次數 \(x\) 子樹的深度有關,就可以直接長鏈剖分+分治NTT做到 \(O(n\log^2n)\)

  否則就要用重鏈剖分+分治NTT。復雜度為 \(O(n\log^3n)\)

  但是我們可以在全局平衡二叉樹上面合並。

  一個點 \(x\)\(size_{ls}\leq \frac{1}{2}size_x,size_{rs}\leq \frac{1}{2}size_x,\max(size_v)\leq \frac{1}{2}size_x\)(這里 \(v\)\(x\) 的輕兒子(虛兒子))。

  這樣只會跳 \(O(\log n)\) 次實邊。

  那虛邊呢?

  如果是和子樹深度有關的題,直接把 \(f_v\) 加起來就好了。總復雜度為 \(O(n\log^2n)\)

  如果是和子樹大小有關的題,可以再用一次全局平衡二叉樹的思想:找到一個點 \(v\) 滿足 \(size_{ls}\leq \frac{1}{2}\sum size_v,size_{rs}\leq \frac{1}{2}\sum size_v\),但是中間那個兒子的 \(size_y\) 可能會 \(>\frac{1}{2}\sum size_v\)。但這並不影響復雜度,因為 \(size_y<\frac{1}{2}size_x\),所以從一個點的某個虛兒子 \(v\) 跳到 \(x\) 需要的步數是 \(O(\log\frac{\sum size_v}{size _v}+1)=O(\log \frac{size_x}{size_v})\)。所以總的復雜度就是 \(O(n\log^2n)\)

DP優化

  記 \([l_i,r_i]\)\(i\in g(k-1)\) 可以轉移到的 \(g(k)\) 中的區間(或者能轉移到 \(g(k)\) 的區間)。要求任意兩個 \([l_i,r_i],[l_j,r_j]\) 不互相嚴格包含。(這里嚴格包含指的是包含且左端點不同且右端點不同)
  我們可以把 \(g(k)\) 切成若干個區間,滿足 \([l_i,r_i]\) 不被任意一個區間嚴格包含,且 \([l_i,r_i]\) 最多與兩個區間相交。
  方法如下:對於一個區間的左端點,找到最右的右端點使得這個區間不嚴格包含任何 \([l_i,r_i]\)。可以證明,這個方法滿足條件。
  這樣,一個 \([l_i,r_i]\) 一定是一個區間的前綴或后綴,分兩部分DP一下就好了。DP過程類似決策單調性優化DP。

區間加&區間 \(\gcd\)

\[\gcd(a_1,a_2,\ldots,a_n)=\gcd(a_1,a_2-a_1,a_3-a_2,a_4-a_3,\ldots,a_n-a_{n-1}) \]

  維護差分后的序列即可。

數位DP

  有時候會遇到很多個數的和 \(\leq m\),每個數 \(\leq n\),還有一些其他限制的計數題。
  可以從低位往高位數位DP,記錄進位和只考慮低位的大小關系。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM