[知识学习] 分块

时间:2020-01-14
本文章向大家介绍[知识学习] 分块,主要包括[知识学习] 分块使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

贴个板子,供自己看

分块核心:暴力操作

左端不完整区间,右端不完整区间暴力计算

中间完整区间lazy标记

#include <bits/stdc++.h>
#define N (100000+5)
using namespace std;
int n,k,a[N],lazy[N],pos[N],L[N],R[N];//a原数组,lazy懒标记,pos[i]:i对应的块,L[i]:块i的左端点,R[i]:块i的右端点
void add(int l,int r,int c){//区间加
    for(int i=l;i<=min(R[pos[l]],r);i++){//左端不完整区间处理
        a[i]+=c;
    }
    if(pos[l]!=pos[r]){
        for(int i=L[pos[r]];i<=r;i++){//右端不完整区间处理
            a[i]+=c;
        }
    }
    for(int i=pos[l]+1;i<pos[r];i++) lazy[i]+=c;//中间完整区间处理
}
int main(){
    scanf("%d",&n);
    k=sqrt(n);//每k个数分1块
    int sum=n/k+(n%k!=0);//共分sum个块
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) pos[i]=(i-1)/k+1;//每个数在哪个块
    for(int i=1;i<=sum;i++) L[i]=(i-1)*k+1,R[i]=i*k;//左右端点
    R[sum]=n;
    for(int i=1;i<=n;i++){
        int opt,l,r,c;
        scanf("%d%d%d%d",&opt,&l,&r,&c);
        if(opt==0) add(l,r,c);
        else if(opt==1) printf("%d\n",a[r]+lazy[pos[r]]);
    }
    return 0;
}

$flag 上一页 下一页