ACM入门之【分块】
生活随笔
收集整理的這篇文章主要介紹了
ACM入门之【分块】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
分塊是一種思想,而不是一種數(shù)據(jù)結(jié)構(gòu)。
分塊的基本思想是,通過對原數(shù)據(jù)的適當(dāng)劃分,并在劃分后的每一個塊上預(yù)處理部分信息,從而較一般的暴力算法取得更優(yōu)的時間復(fù)雜度。
分塊的時間復(fù)雜度主要取決于分塊的塊長,一般可以通過均值不等式求出某個問題下的最優(yōu)塊長,以及相應(yīng)的時間復(fù)雜度。
分塊是一種很靈活的思想,相較于樹狀數(shù)組和線段樹,分塊的優(yōu)點是通用性更好,可以維護(hù)很多樹狀數(shù)組和線段樹無法維護(hù)的信息。
當(dāng)然,分塊的缺點是漸進(jìn)意義的復(fù)雜度,相較于線段樹和樹狀數(shù)組不夠好。
不過在大多數(shù)問題上,分塊仍然是解決這些問題的一個不錯選擇。
一般取塊的長度為 len=sqrt(n), 此時單次操作的時間復(fù)雜度最優(yōu),時間復(fù)雜度為:O( n\sqrt{n}n? )
分塊算法大致分為如下幾步:
- 求分塊后,一個塊的大小。
- 對每個數(shù)都標(biāo)記其對應(yīng)所屬的塊。
- 在執(zhí)行操作的時候,對于不完整的塊暴力處理,完整的塊進(jìn)行處理的標(biāo)記。
分塊標(biāo)記每個編號所屬的塊的模板:
len = sqrt(n); for (int i = 1; i <= n; i++) id[i]=(i-1)/len+1;區(qū)間修改,單點查詢模板:
const int N = 1e5 + 10; typedef long long int LL; LL a[N], ad[N], id[N], n, m, len; //ad[i] 編號為i的塊加的總數(shù) id[i] i所對應(yīng)的塊 void add(int l, int r, int v) //[l,r]內(nèi)加v {for (int i = l; i <= min(r * 1ll, id[l]*len); i++) a[i] += v; //開頭的不完整的if (id[l] == id[r]) return;//在一個塊里for (int i = id[l] + 1; i <= id[r] - 1; i++) ad[i] += v;//中間完整的塊for (int i = (id[r] - 1) * len + 1; i <= r; i++) a[i] += v;//結(jié)束不完整的 } LL query(int x) //查詢x的位置的值 {return a[x] + ad[id[x]]; }總結(jié)
以上是生活随笔為你收集整理的ACM入门之【分块】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 136. 邻值查找【set lower_
- 下一篇: ACM入门之【分块习题】