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