完整**
如何寫分塊(二)
所謂分塊演算法,就是講乙個序列分成若干塊,維護塊內的資訊。為了保證一定的時間複雜度,所以對於乙個
n n
個元素組成的陣列,將其分為
n' role="presentation">n−−
√n塊,每塊也有n−
−√n
個元素。所以一般分塊演算法的複雜中都帶有根號。
對於乙個暴力的區間修改問題,方法自然是對於區間的每乙個元素都暴力修改,這樣的話時間複雜度是明顯不夠優秀的。所以引入了分塊的演算法,分塊相當於一種優雅的暴力。
在分塊中,我們需要維護的基本內容有:總的元素個數
n n
,每一塊的個數bl
ock' role="presentation">blo
ckbl
ock,塊的總數目nu
m num
,這塊左端點的位置l[
i]l [i
],這塊右端點的位置r[
i]r [i
],元素da
ta[i
] dat
a[i]
具體屬於那一塊,根據具體情況,可以適當修改。
下面就對上面需要進行預處理的一一解釋。
這個就很簡單,根據分塊的思想,每一塊要維護n−
−√n
個元素,故每一塊的個數bl
ock=
(√n)
b lo
ck=(
n)
。總共分為bl
ock blo
ck
個塊,那麼每一塊就有nu
m=nb
lock
n um
=nbl
oc
k個元素,這時候要注意是否能整除,若可以則恰好分完,否則nu
m+1 num
+1
。如果我們求出了每一塊的左右端點,那麼也就相當於計算出了每一塊所維護資訊的左右區間,由於每一塊有bl
ock blo
ck
個元素,我們這裡設第
i i
塊所維護的區間為[l
[i],
r[i]
]' role="presentation">[l[
i],r
[i]]
[l[i
],r[
i]],則有如下的式子:l[
i]=(
i−1)
∗blo
ck+1
,r[i
]=i∗
bloc
k l[i
]=(i
−1)∗
bloc
k+1,
r[i]
=i∗b
lock
這樣便可以求解出每塊所維護的區間。
自然我們想到用元素下標
i i
去除以每塊的個數bl
ock' role="presentation">blo
ckbl
ock,這樣的話,當i=
bloc
k i=b
lock
的時候顯然是不正確的,故稍作修正be
long
[i]=
i−1b
lock
+1b el
ong[
i]=i
−1bl
ock+
1即可。
int n,m,num,block;
int l[nmax],r[nmax],belong[nmax];
void build()
上面的一些基本的內容,只是為了我們更快的維護其他的資料,以達到題目的要求,如果有線段樹的基礎,你可以把分塊理解為既加強又退化的線段樹。
為什麼這麼說呢?
在我個人看來,線段樹相當於對原陣列不斷進行分塊,直到最後不可再分。由於一塊分2塊,2塊分4塊,這樣的性質保證了複雜度在lo
g2n log
2n
的數量級上。而分塊只分一次,每塊n−
−√n
個元素。
由於線段樹所分塊太多,所以在面對不符合區間加法的時候,就會顯得十分無力。對於分塊,可以採用部分暴力部分利用塊內資訊來統計。
這裡推薦黃學長的 「分塊」數列分塊入門1 – 9 by hzwer,做題位址在loj。
黃雪長的部落格有詳細的解法和**。
to be continue.
分塊演算法學習筆記
分塊簡介 分塊的基本思想是通過對原資料的適當劃分,並在劃分後的每乙個塊上預處理部分資訊,從而較一般的暴力演算法取得更優的時間複雜度。如何分塊 一般的,我們會把原陣列分成塊長為 sqrt 的幾段,初始化的複雜度為 o n 單次操作的複雜度是 o sqrt p3372 模板 線段樹 1 參考題目可以發現...
分塊演算法入門
分塊演算法是一種較高效的暴力方法,他的思想如下 如名,它將乙個序列分為多段的形式,並將這些段重新分劃出乙個所屬空間,在區間問題求解的時候我們可以整段整段的去求解,而由於我們所面對的區間問題時常是一對很靈活的值,所以我們再求解的時候一般都是先求這個所求區間中所能保留的完整的段,然後在向左向右微調,顯然...
演算法學習 KMP入門
如何進行匹配 kmp解決的是模式串 s s 和文字串 t role presentation t t之間的匹配問題。傳統和暴力演算法,在複雜度方面不夠優秀,根本原因在於對模式串沒有的規律沒有加以利用,導致進行了多餘的匹配。而kmp演算法的關鍵也在於ne xtn ex t陣列,求解出了模式串ne xt...