区间处理之分块

分块这种思路很常见,就是把一个数列划分成k块,然后在块的基础上进行操作。

假如每块的大小为magic,那么长度为n的数列则一共会划分成ceil(n/magic)块。这样会有一些性质:

  1.原数列第i个的块号为i/magic,是块内的第i%magic个(不过这一条没有用)。

  2.假如i%magic==0,说明i是第i/magic块的起点,第i/magic块的范围是[i/magic, (i+1)/magic)。

下面是用分块思想对一个长为n的数列的操作:查找子区间的最大值和修改某个点的值。

 1 const int maxn = 50500;
 2 const int magic = 10;
 3 int n, q;
 4 int h[maxn], b[maxn];
 5 
 6 void init() {
 7     for(int i = 0; i < n; i++) {
 8         if(i % magic == 0 || h[i] > b[i/magic]) {
 9             b[i/magic] = h[i];
10         }
11     }
12 }
13 
14 int query(int l, int r) {
15     int ret = h[l];
16     for(int i = l; i <= r; ) {
17         if(i % magic == 0 && i + magic - 1 <= r) {
18             ret = max(ret, b[i/magic]);
19             i += magic;
20         }
21         else {
22             ret = max(ret, h[i++]);
23         }
24     }
25     return ret;
26 }
27 
28 void update(int x, int v) {
29     h[x] = v;
30     int l = x / magic * magic;
31     int r = l + magic;
32     for(int i = l; i < r; i++) {
33         if(i % magic == 0 || h[i] > b[i/magic]) {
34             b[i/magic] = h[i];
35         }
36     }
37 }
原文地址:https://www.cnblogs.com/kirai/p/5874829.html