分块算法及模板

Posted

tags:

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

此文为博主原创,转载时请通知博主,并把原文链接放在正文醒目位置。

 

简要介绍

分块算法就是把一串数据分割成几块数据的算法,其实是对暴力的一种优化。

通常在分块时,每块的大小为√n。但最后一块的大小也可能小于√n,只能用暴力来算。

通过把对单个数据的操作转化为对几个块的数据的操作,能够节省时间,提高运算效率。

分块算法在处理大范围的修改、查询问题时有很大优势。

 

分块算法代码

 1 /*此代码主要模仿了钟皓曦大佬的分块算法*/
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 const int MAXN = 1000005;
 9 const int MAXP = 1005;
10 int belong[MAXN],size[MAXP],sum[MAXP],add[MAXP];
11 //    所属块        块的大小    块内计和  添加标记 
12 int a[MAXN];
13 int s,cnt;
14 
15 void init()
16 {//初始化操作 
17     s = sqrt(n);//每个块的大小 
18     for(int i = 1;i <= n;i ++)
19         belong[i] = (i-1)/s + 1;
20     //每个数的所属块 
21     cnt = belong[n];//块的数量 
22     
23     for(int i = 1;i <= cnt;i ++)
24     {//记录块的大小 
25         sum[i] = add[i] = 0;
26         if(i == cnt)
27         {
28             if(n%s == 0)    size[i] = s;
29             else    size[i] = n%s
30         //求最后一个块的大小 
31         }
32         else size[i] = s;
33     } 
34 }
35 
36 int query(int l,int r)
37 {//询问操作 
38     int ans = 0;
39     if(belong[l] == belong[r])
40         ans += sum[belong[l]];
41     //询问区间在一个块里的情况
42      
43     while(belong[l] == belong[l - 1])
44     {//询问区间在整块左侧的情况 
45         ans += a[l] + add[belong[l]];
46         l ++; 
47     }
48     while(belong[r] == belong[r + 1])
49     {//询问区间在整块右侧的情况 
50         ans += a[r] + add[belong[r]];
51         r --;
52     }
53     for(int i = belong[l];i <= belong[r];i ++)
54     //对整块进行求和操作 
55         ans += sum[i];
56     return ans; 
57 }
58 
59 void modify(int l,int r,int k)
60 {//修改(增减值)操作 
61     if(belong[l] == belong[r])
62     {//修改区间在一个块内的情况 
63         for(int i = l;i <= r;i ++)
64             a[i] += v;
65         return;
66     }
67     while(belong[l] == belong[l - 1])
68     {//修改区间在整块左侧的情况 
69         a[l] += v;
70         l ++;
71     }
72     while(belong[r] == belong[r + 1])
73     {//修改区间在整块右侧的情况 
74         a[r] += v;
75         r --;
76     }
77     for(int i = belong[l];i <= belong[r];i ++)
78     {//对整块进行增减操作 
79         add[i] += v;//标记一个块 
80         sum[i] += size[i]*v;
81     }
82 }

 

分块算法例题

洛谷 P1903 【模板】分块/带修改莫队(数颜色)   https://www.luogu.org/problem/show?pid=1903

洛谷 P2801 教主的魔法   https://www.luogu.org/problem/show?pid=2801  (数据较弱)

(不知道为什么,洛谷的算法标签里没有“分块”)

 

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

高级数据结构分块莫队笛卡尔树算法模板几题

分块代码

Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]

算法竞赛模板(数论)

算法复习——分块算法

分块,莫队算法总结