分块浅谈

其实分块是一种我认为比较简单的算法,可以看作一种暴力。。。


步入正题

分块的思想其实就是在进行区间修改时,将序列分成几块,如果要修改的区间有一个整块的话,将这一个整块做一个标记,其他部分就暴力修改就好了。


例题一

给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。

先讲一下区间修改

这是最基本的区间修改(a,b):

for(int i=a;i<=min(k[a]*ks,b);i++)
    v[i]+=c;
if(k[a]!=k[b])
    for(int i=(k[b]-1)*ks+1;i<=b;i++)
        v[i]+=c;
for(int i=k[a]+1;i<=k[b]-1;i++)
    bj[i]+=c;

k[i] 表示第 \(i\) 个数在哪个块中
bj[i] 表示第 \(i\) 块这一整块所加上的数
v[i] 表示第 \(i\) 个数的值

其中
for(int i=a;i<=min(k[a]*ks,b);i++)
是暴力枚举以a为左端点时不完整的块中的每一个数。

for(int i=(k[b]-1)*ks+1;i<=b;i++)
是暴力枚举以b为右端点时不完整的块中的每一个数。

for(int i=k[a]+1;i<=k[b]-1;i++) bj[i]+=c;是对\(a\)\(b\)之间的整块进行整块标记。

单点查询:

v[r]+bj[k[r]]

即该点的值加上它所在的块的标记
然后输出即可

(未完待续)

猜你喜欢

转载自www.cnblogs.com/LCGUO/p/12298265.html