1zoj A simple problem with integer 2|板子|分块

Posted saitoasuka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1zoj A simple problem with integer 2|板子|分块相关的知识,希望对你有一定的参考价值。

目录

分块算法

算法思想

引用某次考试Problem上的(伪)Pre reading(题解):

分块算法:
分块很像线段树,但是比线段树看起来更“暴力”一些,写起来更简单一些(期望得分80),用来维护复杂的区间信息时更容易一些。基本思想:可以把具有n个元素的集合分解成√n段,每一段的长度为√n (当然,最后一段可能不够)。对于任意一个区间操作[L,R],可将其分解成三部分。
技术分享图片
例如当n=16,L=3,R=10:
[L,R]区间可分解为:两端可能不足一个块长度的区域(1和3),和中间的若干完整块(2)。信息维护:对于中间的若干完整块,可以采取整体操作的方式(一般打lazytag),两边的零散块采用暴力的方式。
例如:区间修改
1、计算块长度len=√n
2、预处理单点所在的块编号b [i]=(i-1)/len+1 (若编号都是从1开始)
3、暴力更新左边[L,min(b [L]*len,R)], 中间打标记(从块b [L]+1到b [R]-1),暴力更新右边(可能不存在)。。。

板子题

技术分享图片

板子代码

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define LL long long
using namespace std;
void read(LL &n){
    LL num=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        num=num*10+ch-'0';
        ch=getchar();
    }
    n=num*w;
}
const int maxn=1e5+5;
LL n,m;
int blo/*每个块的长度*/,bl[maxn];//每个块的编号
LL a[maxn],tag[maxn]/*懒标记*/,sum[maxn];
//预处理 
void init(){
    read(n);read(m);
    blo=sqrt(n);
    for(int i=1;i<=n;i++){
         read(a[i]);
         bl[i]=(i-1)/blo+1;//计算每个节点所在的块编号
         sum[bl[i]]+=a[i]; 
    }
}
//区间和查询 
LL query(int l,int r){
    LL ans=0;
    //暴力计算左边 
    for(int i=l;i<=min(bl[l]*blo,r);i++)
        ans+=a[i]+tag[bl[l]];
    //暴力计算右边 
    if(bl[l]!=bl[r])
        for(int i=(bl[r]-1)*blo+1;i<=r;i++)
            ans+=a[i]+tag[bl[r]];
    //整块计算中间
    for(int i=bl[l]+1;i<=bl[r]-1;i++)
        ans+=sum[i]+blo*tag[i];
    return ans;
}
//区间修改
void update(int l,int r,LL c){
    //暴力修改左边 
    for(int i=l;i<=min(bl[l]*blo,r);i++)
        a[i]+=c,sum[bl[l]]+=c;
    //暴力修改右边 
    if(bl[l]!=bl[r])
        for(int i=(bl[r]-1)*blo+1;i<=r;i++)
            a[i]+=c,sum[bl[r]]+=c;
    //整块修改中间
    for(int i=bl[l]+1;i<=bl[r]-1;i++)
        tag[i]+=c;
}
int main(){
    init();
    for(int i=1;i<=m;i++){
        char ord;cin>>ord;
        LL a,b;read(a);read(b);
        if(ord=='Q') printf("%lld
",query(a,b)); 
        else{
            LL c;read(c);
            update(a,b,c);
        }
    }
    return 0;
}

以上是关于1zoj A simple problem with integer 2|板子|分块的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1757 A Simple Math Problem

A Simple Problem

A Simple Problem

poj 3466 A Simple Problem with Integers

A Simple Problem with Integers

A Simple Math Problem HDU - 5974