树状数组--区间加单点询问

我们知道,线段树用来做单点修改是很方便的,那么,既然这么方便,为什么不能用它来做区间修改呢?好吧,我们来试试看:

首先不难想到要把区间修改转化为前缀修改,即,将把 [L,R] 这段区间加 k ,变成把[1,R]加k,再把 [1,L1] 减去 k ,这显然是正确的。

那么我们来考虑如何维护这个东西,考虑Ai表示 [1,i] 这个前缀的增量,那么考虑将一个点 x 的值增加了k,这个操作会对整个 A 数组造成什么影响。

显然需要分两种情况讨论:

1i<x

对于这样的 Ai ,显然它会增加 ik

2ix

对于这样的 Ai ,显然它会增加 xk

接下来我们来考虑如何求 Ai ,显然,我们需要把上述两种情况进行相加得到真正的 Ai ,考虑第一种情况,现在我们要求的是所有大于 i x的增量,所以我们需要求的是后缀和,我们只需要维护一个树状数组,询问所有大于 i x的k值,询问的时候把这个值最后 i 即可。对于第二种情况,我们要求的显然是前缀和,只要直接维护 xk 的树状数组,每次询问前缀和就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100006
#define lowbit(x) (x&-x)
#define LL long long
using namespace std;
inline char nc(){
    static char buf[100000],*i=buf,*j=buf;
    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline LL _read(){
    char ch=nc();LL sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum;
}
int n,tet;
LL a[maxn],f1[maxn],f2[maxn];
void put1(int x,LL y){for(;x<=n;x+=lowbit(x))f1[x]+=y;}
LL get1(int x){
    if(x<0)return 0;
    int sum=0;
    for(;x;x-=lowbit(x))sum+=f1[x];
    return sum;
}
void put2(int x,LL y){for(;x<=n;x+=lowbit(x))f2[x]+=y;}
LL get2(int x){
    if(x<0)return 0;
    LL sum=0;
    for(;x;x-=lowbit(x))sum+=f2[x];
    return sum;
}
void put(int l,int r,LL k){
    if(l>1)put1(l-1,-k),put2(l-1,(1-l)*k);
    put1(r,k);put2(r,r*k);
}
LL get(int x){return x*(get1(n)-get1(x))+get2(x);}
int main(){
    freopen("temp.in","r",stdin);
    freopen("temp.out","w",stdout);
    n=_read();tet=_read();
    for(int i=1;i<=n;i++) a[i]=a[i-1]+_read();
    while(tet--){
        int k=_read();
        if(k==1){
            int l=_read(),r=_read(),x=_read();
            put(l,r,x);
        }else{
            int l=_read(),r=_read();
            printf("%lld\n",a[r]-a[l-1]+get(r)-get(l-1));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值