什么是分块
分块,顾名思义是一种将数据分成多块,以实现一些功能的算法。
分块算法实质上是一种是通过将数据分成多块后在每块上打标记以实现快速区间修改,区间查询的一种算法。其均摊时间复杂度为 \(O(\sqrt{n} )\)
分块的具体操作
分块
void create() {
t=sqrt(n);
for(int i=1;i<=t;i++) { //每个块的区间
l[i]=(i-1)*t+1;
r[i]=i*t;
}
if(r[t]<n) { t++;l[t]=r[t-1]+1,r[t]=n; }
for(int i=1;i<=t;i++) {
for(int j=l[i];j<=r[i];j++){
pos[j]=i; //每个数对应的块
}
}
/*一些预处理*/
}
一些操作
单点操作
区间操作
//区间修改
void change(int l,int r,int d) {
int p=pos[l],q=pos[r];
if(p==q) {
for(int i=l;i<=r;i++) a[i]+=d;
//sum[p]+=d*(r-l+1);
/*同时需要注意一些数据的更新,如区间和*/
}
else {
for(int i=p+1;i<=q-1;i++) add[i]+=d;
for(int i=l;i<=R[p];i++) a[i]+=d;
//sum[p]+=d*(R[p]-l+1);
/*同时需要注意一些数据的更新,如区间和*/
for(int i=L[q];i<=r;i++) a[i]+=d;
//sum[q]+=d*(r-L[q]+1);
/*同时需要注意一些数据的更新,如区间和*/
}
return;
}
//区间查询 区间和
int ask(int l,int r) {
int p=pos[l],q=pos[r];
int ans=0;
if(p==q) {
for(int i=l;i<=r;i++) ans+=a[i];
ans+=add[p]*(r-l+1);
}
else {
for(int i=p+1;i<=q-1;i++) ans+=sum[i]+add[i]*(R[i]-L[i]+1);
for(int i=l;i<=R[p];i++) ans+=a[i];
ans+=add[p]*(R[p]-l+1);
for(int i=L[q];i<=r;i++) ans+=a[i];
ans+=add[q]*(r-L[q]+1);
}
return ans;
}