分塊系列 數列分塊入門1 解題報告

2022-04-29 20:57:10 字數 1367 閱讀 5783

區間加法,單點求值。

數列分塊是個好東西。。。我這裡詳細介紹一下分塊演算法,便於初學者的理解(我這個蒟蒻原來也是看不懂分塊)。

先把陣列分成幾個塊塊,然後就可以對它們整體操作啦。

也就是說,把乙個長度為的陣列,拆分成乙個個長度為sqrt(n)小塊(當然,最後一塊可能不完整,但是不用管),記錄每個數所屬的塊;也就是這樣——(方便起見,我們直接再開乙個陣列來記錄所屬分塊,雖然本題中可以臨時計算,但在有些題目中這一步顯得尤為重要)

scanf( "%d", &n );

m = (int)sqrt(n);

for ( int i = 1; i <= n; ++i ) p[i] = ( i - 1 ) / m + 1;

for ( int i = 1; i <= n; ++i ) scanf( "%d", &a[i] );

然後,就可以瞎暴力辣!

實際上,所有的分塊都是這樣。把乙個數列分成幾塊,然後對它們進行批量處理。一般來說,我們直接把塊大小設為sqrt(n),但實際上,有時候我們要根據資料範圍、具體複雜度來確定。

當有修改時,對於完整的塊,直接維護乙個陣列v記錄整個塊加過的數(每塊共同的加數),不完整的就直接暴力在原陣列a上直接加。詢問時,直接輸出原陣列的值+所屬塊的共同加數即可。

#include#includeusing namespace std;

#define maxn 50005

int n, a[maxn], p[maxn], m, v[300];

int opt, l, r, c;

void add( int l, int r, int c )

for ( int i = l; p[i] == p[l]; ++i ) a[i] += c;//對於兩邊不完整(即使完整也不管,看做不完整)的分塊,直接暴力即可

for ( int i = r; p[i] == p[r]; --i ) a[i] += c;

for ( int i = p[l] + 1; i <= p[r] - 1; ++i ) v[i] += c;//記錄完整分塊的共同加數

}int main()

return 0;

}

分塊**可以比線段樹簡潔不少,雖然暴力但十分巧妙,而且十分靈活,適用於更多的題目。

但是如果時間複雜度要求較高,分塊的o(n sqrt(n))就不能承受了,所以還是要學會乖乖打線段樹qaq。

數列分塊入門1

<-

數列分塊入門2

數列分塊入門3

數列分塊入門4

數列分塊入門5

數列分塊入門6

數列分塊入門7

數列分塊入門8

數列分塊入門9

蒲公英公主的朋友

分塊系列 數列分塊入門7 解題報告

區間乘法,區間加法,單點詢問。寫過線段樹模板2的童鞋應該很清楚了吧qaq 由於 與markdown衝突,所以用 代替o o 我們把乙個數表示為 a i tg2 b i tg1 b i tg2表示乘法標記,tg1表示加法標記。對於不完整的塊,直接 a i a i tg2 b i tg1 b i 將這個...

分塊系列 數列分塊入門6 解題報告

單點插入,單點詢問。分塊的小技巧可多啦 o o哈哈 用乙個vector來記錄每個塊的元素。vector提供了強大的insert函式,插入某個元素只要寫一點點就可以啦o o,就是乙個乙個列舉塊,直到找到插入位置屬於哪個塊,然後insert一下就ok。不過,如果插入元素集中於乙個塊的話就尷尬了qaq複雜...

LOJ 數列分塊入門 1

link 優雅的暴力,對於乙個數列,他不是乙個元素乙個元素處理,而是分成若干塊,成塊成塊的處理,以此達到降低時間複雜度的目的。首先,我們需要處理劃分的塊的大小 block 一般是根號n 塊的數目 每乙個元素對應第幾塊,然後,每一塊的左端點和右端點。完整的塊 更新 我們用lz i lz i lz i ...