这几天学习了分块和莫队
“分块和莫队都是优雅的暴力”--数据结构带师wsk_1202
确实,分块的主要思想就是将两端暴力处理,中间拿tag标记或其他途径维护一下,将修改与询问的时间复杂度分摊,达到(O(nsqrt{n}))的时间复杂度
这一个题库里涉及了很多分块的基本操作和用法,有时间可以多看一看
放一个分块入门1的代码
#include<bits/stdc++.h>
using namespace std;
int n,a[50003],tag[50003],pos[50003],typ,m,l,r,c;
void add(int l1,int r1,int num)
{
for(int i=l1;i<=min(r1,pos[l1]*m);i++) //枚举左边界
a[i]+=num;
if(pos[l1]!=pos[r1])
for(int i=(pos[r1]-1)*m+1;i<=r1;i++) //枚举右边界
a[i]+=num;
for(int i=pos[l1]+1;i<=pos[r1]-1;i++) //枚举中间的整块
tag[i]+=num;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
m=sqrt(n); //还可以取pow(n,0.33)或pow(n,0.4)等等
for(int i=1;i<=n;i++)
pos[i]=(i-1)/m+1; //统计每个元素所在的块
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&typ,&l,&r,&c);
if(typ==0)
add(l,r,c);
else
cout<<a[r]+tag[pos[r]]<<endl;
}
return 0;
}
分块的代码是不是看起来就很暴力
在洛谷上写分块的时候写到了一个题,这道题巧妙地运用了分块的思想(貌似是根号分治),把原本预处理(O(n^2)),询问(O(1)),均摊一下,变成了预处理(O(nsqrt{n})),询问(O(nsqrt{n})),从而实现了均摊复杂度,是一种很巧妙地思想