分块动态求和

不会的同学可以先参考这个博客

https://blog.csdn.net/weixin_43914593/article/details/108474903

题目;loj6280

题目描述

给出一个长为  的数列,以及  个操作,操作涉及区间加法,区间求和。

输入格式

第一行输入一个数字 

第二行输入  个数字,第  个数字为 ,以空格隔开。

接下来输入  行询问,每行输入四个数字 ,以空格隔开。

若 ,表示将位于  的之间的数字都加 

若 ,表示询问位于  的所有数字的和 

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename Tp>
void read(Tp &x){
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch>'9'||ch<'0')){
        ch=getchar();
    }
    if(ch=='-'){
        fh=-1;ch=getchar();
    }else fh=1;
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    }
    x*=fh;
}
inline char read1()
{
    register char ch=getchar();
    while(ch<'A'||ch>'M')ch=getchar();
    return ch;
}
const int maxn=1e6+100;
ll a[maxn],l[maxn],r[maxn],belong[maxn],lazy[maxn],ans;
ll sum[maxn];
ll n,op,x,y,k,block,tot;
void build(){
    block=sqrt(n);
    tot=n/block;
    if(n%block){
        tot++;
    }
    for(register int i=1;i<=n;i++){
        belong[i]=(i-1)/block+1;
    }
    for(register int i=1;i<=tot;i++){
        l[i]=(i-1)*block+1;
        r[i]=i*block;
    }
    r[tot]=n;
    for(int i=1; i<=tot; i++){                 //遍历所有的块
        for(int j=l[i]; j<=r[i];j++)      //遍历块i内的所有元素
            sum[i] += a[j];//一个块中的和 
    } 
}
void change(){
    if(belong[x]==belong[y]){
        for(register int i=x;i<=y;i++){
            a[i]+=k;
            sum[belong[x]]+=k;
        }
    }
    else{
        for(register int i=x;i<=r[belong[x]];i++){
            a[i]+=k;
            sum[belong[x]]+=k;
        }
        for(register int i=l[belong[y]];i<=y;i++){
            a[i]+=k;
            sum[belong[y]]+=k;
        }
        for(register int i=belong[x]+1;i<belong[y];i++){
            lazy[i]+=k;//懒惰标记 
        }
    } 
}
void ask(){
    ans=0;
    if(belong[x]==belong[y]){
        for(register int i=x;i<=y;i++){
            ans=(ans+lazy[belong[x]]+a[i])%(k+1);//不要忘记懒惰标记 
        }
        printf("%lld\n",ans%(k+1));
    }
    else{
        for(register int i=x;i<=r[belong[x]];i++){
            ans=(ans+lazy[belong[x]]+a[i])%(k+1); 
        }
        for(register int i=l[belong[y]];i<=y;i++){
            ans=(ans+lazy[belong[y]]+a[i])%(k+1);
        }
        for(int i=belong[x]+1;i<belong[y];i++){
            ans=(ans+1ll*sum[i]+(r[i]-l[i]+1)*lazy[i])%(k+1);//不要忘记懒惰标记,和sum[i] 
        } 
        printf("%lld\n",ans%(k+1));
    }
    
} 
int main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    build();
    for(int i=1;i<=n;i++){
        read(op),read(x),read(y),read(k);
        if(op==0){
            change();
        }
        else{
            ask();
        }
    } 
}

 

posted @ 2020-09-15 14:39  lipu123  阅读(172)  评论(0编辑  收藏  举报