分塊

數列上的分塊

複習一下

當我們想要做RMQ(區間極值)時

我們會使用sparse table, 線段樹...

但其實有另一個做法,稱作分塊

分塊

7 1 2 4 6 3 8 9 5
7 6 9

每\(K\)格記錄答案

詢問

7 1 2 4 6 3 8 9 5
7 6 9

若有覆蓋到整塊->直接查

沒被蓋到的最多\(2K\)->暴力做

修改

7 1 2 4 0 3 8 9 5
7 4 9

只會影響到那塊

就暴力跑完,維護好答案

複雜度

詢問: \(O(N/K+K)\)

修改: \(O(K)\)

根據算幾不等式,\(K+(N/K)\geq 2\sqrt{K\times (N/K)}\)

等號成立條件: \(K=N/K\)

所以當\(K=\sqrt N\)時,複雜度最好

等等...

以前提到的BIT、線段樹複雜度都是\(O(logN)\)

比分塊更好,那分塊有什麼用?

  • (可能)比較好寫
  • 處理一些資料結構做不到或不好做的事

例題

中國人插隊問題

有 \(N\) 筆操作

\(1  x  id\): 編號為 \(id\) 的人插隊到第 \(x\) 個位置

\(2  x\): 排在第 \(x\) 個位置的人走了

\(3  x\): 詢問排在第 \(x\) 個位置的人的編號

不那麼直覺的分塊

Counting Triangles

給定一張圖,\(N\)個點\(M\)條邊

對於三個點 a, b, c (a<b<c),若a,b和b,c和c,a之間都有邊

則 a, b, c 形成一個三角形。

請問整張圖總共有多少三角形?

\(N,  M\leq 10^5\)

Counting Triangles

假設我們可以\(O(1)\)回答\((x,y)\)之間是否有一條邊

那麼對於圖上任意一點 \(v\),可以

  1. \(O(M)\) 時間算出有多少個包含點 \(v\) 的三角形
  2. \(O(d^2)\) 時間算出有多少個包含點 \(v\) 的三角形     (\(d\) 為 \(v\) 的點度)

Counting Triangles

對於點度 \(< K\) 的點,我們花 \(O(\sum d_i^2)\) 時間做

\(O(\sum d_i^2)=O(K\times \sum d_i)=O(K\times M)\)

剩下的點花 \(O(M\times C)\) 的時間做

定義 \(C\) 為點度 \(\geq K\) 的點數數量

可以得知,\(C\leq 2M/K\)

總複雜度: \(O(K\times M+M^2/K)\)

取 \(K=\sqrt M\) 時有最好複雜度 \(O(M\sqrt M)\)

Codeforces 1207F

給一個長度為 \(5\times 10^5\) 的序列(初始為全零),有 \(Q\) 筆操作

\(1  x  y\) : 將第 \(x\) 個數字加上 \(y\)

\(2  x  y\) : 求序列中所有編號除以 \(x\) 餘 \(y\) 的數字和

\(Q \leq 5\times 10^5\)

TIOJ 1674

給定數字 \(N\),求 \(\sum_{i=1}^{N} N  mod  i\)

\(N\leq 10^{13}\)

2020 NPSC 初賽 pA

有 \(N\) 個人,每 \(x\) 個人一組,從 \(1\) 號開始依序分。定義 \(f(i)\) 為考慮 \(x=1, x=2, ... , x=N\) 這 \(N\) 種情況時,編號 \(i\) 的人分不到組的狀況總數

給定 \(L, R\),求\(f(L), f(L+1), ... ,f(R)\)

\(1\leq N\leq 2^{40}\),\(R-L\leq 3\times 10^5\)

分塊

By jass921026

分塊

  • 644