分块区间加和单点查询

loj:6277

给出一个长为 n 的数列,以及 m 个操作,操作涉及区间加法,单点查值。

输入格式

第一行输入一个数字 

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

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

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

若 ,表示询问  的值( 和  忽略)。

#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;
int a[maxn],l[maxn],d[maxn],r[maxn],belong[maxn],lazy[maxn],ans;
int n,q,block,tot,x,y,k,op;
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;d[i]=a[i];
    }
    for(register int i=1;i<=tot;i++){
        l[i]=(i-1)*block+1;
        r[i]=i*block;
    }
    r[tot]=n;
}
void change(){
    if(belong[x]==belong[y]){
        for(int i=x;i<=y;i++){
            a[i]+=k;
        }
    }
    else{
        for(register int i=x;i<=r[belong[x]];i++){
            a[i]+=k;
        }
        for(register int i=l[belong[y]];i<=y;i++){
            a[i]+=k;
        }
        for(register int i=belong[x]+1;i<belong[y];i++){
            lazy[i]+=k;
        }
    }
}
int main(){
    read(n);
    for(register int i=1;i<=n;i++){
        read(a[i]);
    }
    build();
    for(register int i=1;i<=n;i++){
        read(op); 
        read(x),read(y),read(k);    
        if(op==0){ 
            change();
        }
        else if(op==1){
            printf("%d\n",a[y]+lazy[belong[y]]);
        }
    }
    return 0; 
} 

 

posted @ 2020-09-15 14:50  哎呦哎(iui)  阅读(141)  评论(0编辑  收藏  举报