數列分塊6

2021-09-27 10:16:21 字數 1140 閱讀 2106

題意:給出乙個長為n的數列,以及n個操作,操作涉及單點插入,單點詢問,資料隨機生成。

思路:

先說隨機資料的情況

之前提到過,如果我們塊內用陣列以外的資料結構,能夠支援其它不一樣的操作,比如此題每塊內可以放乙個動態的陣列,每次插入時先找到位置所在的塊,再暴力插入,把塊內的其它元素直接向後移動一位,當然用鍊錶也是可以的。

查詢的時候類似,複雜度分析略。

但是這樣做有個問題,如果資料不隨機怎麼辦?

如果先在乙個塊有大量單點插入,這個塊的大小會大大超過√n,那塊內的暴力就沒有複雜度保證了。

還需要引入乙個操作:重新分塊(重構)

每根號n次插入後,重新把數列平均分一下塊,重構需要的複雜度為o(n),重構的次數為√n,所以重構的複雜度沒有問題,而且保證了每個塊的大小相對均衡。

當然,也可以當某個塊過大時重構,或者只把這個塊分成兩半。

#include using namespace std;

const int maxn = 100005;

int a[maxn],laz[maxn],bl[maxn],block,st[maxn],ed[maxn];

listlis[1005];

int main()

ed[bl[n]] = n;

for( int i = 1;i <= bl[n];i++ )

for( int i = 1;i <= bl[n];i++ )

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

}laz[ p ]++;

l -= sum;

auto it = lis[p].begin();

for( int i = 0;i < l-1;i++ ) it++;

lis[ p ].insert( it,r );

}else

}r -= sum;

list:: iterator it = lis[p].begin();

for( int i = 0;i < r-1;i++ ) it++;

int res = *it;

printf("%d\n",res);}}

return 0;

}

6282 數列分塊入門 6

題目鏈結 插入值過後整個分塊已經不是平均分配了,可能導致某一塊過大,需要重新build,將塊元素平均。第一行輸入乙個數字 n。第二行輸入 n 個數字,第 i 個數字為 ai 以空格隔開。接下來輸入 n 行詢問,每行輸入四個數字 opt l r c,以空格隔開。若 opt 0,表示在第 l 個數字前插...

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

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

LOJ 6282 數列分塊6

題目大意 給定乙個由 n 個數組成的序列,維護兩種操作 單點詢問,單點插入。n 100000 題解 在塊內維護乙個鍊錶,支援動態插入數字,同時對於非隨即資料來說,若塊的大小過大,需要重構。注 對於 c vector 的 insert 函式的含義是在給定迭代器的後面插入數值。如下 include us...