筆記 分塊與塊狀陣列

2022-09-14 16:12:14 字數 1798 閱讀 5608

\[\textsf

\]

對於一系列資料,通過適當的劃分,預處理一部分資訊並儲存下來,用空間換取時間,達到時空平衡。

核心思想還是暴力

把乙個整體劃分為若干個小塊,對整塊整體處理,零散塊單獨處理。

「大段維護,區域性樸素」

事實上,分塊更接近於「樸素」,效率往往比不上線段樹和樹狀陣列,但是他更通用,更容易實現。(對我這樣的蒟蒻更加友好)

一種基於分塊思想處理區間的資料結構。

乙個長度為 \(n\) 的陣列,將其劃分為相同的 \(a\) 塊,每塊的長度為 \(\frak\) 。顯然有時會存在不能完整劃分的區塊,那麼將其單獨處理。

即對於一次區間的操作,對區間內部的整塊進行整體的操作,而對於區間邊緣的零散塊單獨暴力處理。

正是所謂「優雅的暴力」。

然而,塊數的確定又是乙個問題。

為了解決以上問題,一般來說,我們取塊數為 \(\sqrt\) ,這樣即便是在最壞情況下,我們也只需要對大約 \(\sqrt\) 個整塊、 長度為 \(\frac}=2 \sqrt\) 的零散塊進行處理,總時間複雜度為 \(o(\sqrt)\) ,可以接受。

所以,分塊可以說是一種根號級演算法

很顯然,分塊思想的時間複雜度比不上線段樹和樹狀陣列這些可以達到對數級的演算法,但是由此換來的,是更高的靈活性和對新手菜雞蒟蒻(((比如我更良的寫**體驗。

與線段樹不同,塊狀陣列不要求所維護資訊必須滿足結合律,也不用一遇到大的資料就一層層地傳遞標記。

但是它們又有相似之處,可以這麼理解,線段樹是以可高度約為 \(\log_\) 的樹,而塊狀陣列則可以看作是一棵高度僅為 \(3\) 的樹,而且最頂層的資訊不需用維護。

使用塊狀陣列前,先劃分出每個塊所佔據的範圍。

struct block

b[_];

int num = sqrt(n);

for (int i = 1; i <= num; i++)

但是,由於陣列的長度並不一定是乙個完全平方數,那麼我們把遺漏下的那一小塊放入最後乙個塊中,此後對它單獨處理。

b[num].r = n;
然後為每個元素確定其所屬的塊。

for (int i = 1; i <= num; i++)

for (int j = b[i].l; j <= b[i].r; j++)

id[j] = i; // 表示 j 號元素歸屬於第 i 塊

如果需要,我們還可以預處理

接下來用一道線段樹的題目說明塊狀陣列的其他操作。

p3372 【模板】線段樹 1

for (int i = 1; i <= n; i++)

a[i] = read();

for (int i = 1; i <= num; i++)

for (int j = b[i].l; i <= b[i].r; j++)

b[i].sum += a[i];

if (id[x] == id[y])

for (int i = x; i <= y; i++)

ans += a[i] + b[id[i]].lzy; // 注意要加上標記

然後這道題差不多就結束了~

分塊還是要和莫隊結合的吧

完結!

學習筆記 分塊

分塊可以解決幾乎全部的區間查詢區間更新等問題,功能比線段樹和樹狀陣列要強大,但是時間複雜度會更大一點。其實分塊就是一種優化過的暴力,它是對於整體進行像線段樹一樣的維護,對區域性進行暴力的修改。顧名思義分塊分塊,我們把長度為n的序列分為若干塊。維護塊內資訊即可。又要問了,要多大呢?通常將塊的大小設為n...

SQL學習筆記 分塊提取查詢結果

實踐中,資料庫中可能有數十億條記錄。查詢結果有可能達到千萬條。如果用dbgetquery 一次性取出所有查詢結果,記憶體可能吃不消。但是,如果容許分塊處理資料來完成任務,那麼下述方法不失為乙個好的選擇。library dbi library rsqlite con dbconnect sqlite ...

C語言筆記 分配記憶體,malloc與陣列

1.malloc double ptd ptd double malloc n sizeof double 可使用ptd i 來訪問第i個元素,i用malloc 建立二維陣列 int p m p2指向乙個內含m個某型別值的陣列,p2 i 代表乙個由m個此型別數構成的元素 p int m malloc...