分块算法

Posted buhuiflydepig

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分块算法相关的知识,希望对你有一定的参考价值。

分块算法

首先来谈谈什么是分块呢?直接理解就是把一个整体分成若干个部分,这就是所谓的字面理解分块。

就如刚才所说,这就是分块的思想,而分块算法又称优雅的暴力

好啦,现在我们正式来理解分块算法......

 

一般来说,分块吗?你总要知道自己每块要分的大小对吧。这个已经解决了,一般每块都是分为sqrt(n)的大小,而一共有n / sqrt(n)块,当然,如果不能整除的话,你需要分的数量还是要加一的。之后你每块都要有一个标记吧,比如说:你有1,2,3,4,5这5个数,每块的大小是2, 一共3块, 其中 1 和 2 属于一块,3 和 4 属于一块,依次类推。一般存在一个belong[] 数组里面,方便后续操作。嘻嘻...你以为这样就完了吗?那你就错了,还需要一样东西,就是你需要记录每一块的范围,放心,这个很简单的,就是定义两个数组,分别记录在当前块所在范围的左端点和右端点。这个很容易实现的,就是上一个区间的右端点加一,和当前区间的右端点就是所求的范围。是不是有点晕,好吧。我们看一下代码吧,这样便于理解。

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int a[maxn]; //a数组存取原始数据 int belong[maxn]; //belong数组表示每个数属于哪一块方便调用 int L[1010]; //L和R表示各块左右端点 int R[1010]; int block,num; //block各块大小,num块数量 //修改,视情况而定 void change(int l, int r, int add) //略..(可见下面模板题) //查询,同上 int query(int l, int r) //略.. //建立各块(各个分块这个操作大致一样) void build(int n) block = sqrt(n);//每块的大小 num = n / block; //一共有多少块 if (n % block) num++; //如果不整除显然数量加个1 for(int i = 1; i <= num; i++) L[i] = (i - 1) * block + 1; //上一个区间的右端点加一就是当前区间的左端点 R[i] = i * block; //直接计算当前区间的右端点 R[num] = n; //最后一个右端点一定是结尾 for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1; //belong数组 //初始状态维护......(省略)
int main() int n; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); build(n); //询问......(省略)

 

以上是关于分块算法的主要内容,如果未能解决你的问题,请参考以下文章

《夜深人静写算法》数论篇 - (23) 整数分块

算法#1分块

算法实践分块查找知多少?手把手带你实现分块查找

算法复习——分块算法

分块,莫队算法总结

查找算法之折半查找+分块查找