树状数组的区间修改与区间查修
Posted Heey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组的区间修改与区间查修相关的知识,希望对你有一定的参考价值。
考虑差分
sum[i] = a[1]+...+a[i] + delta[1]*i + delta[2]*(i-1)+delta[3]*(i-2)+...+delta[i]*1 // a[i]为原始数组
= sigma(a[x])+sigma(delta[x]*(i+1-x))
= sigma(a[x])+(i+1)*sigma(delta[x])-sigma(delta[x]*x)
所以我们记sum为前缀和,delta[i],deltai[i]=delta[i]*i
//sum[i] = a[1]+...+a[i] + delta[1]*i + delta[2]*(i - 1) + delta[3]*(i - 2)+...+delta[i]*1 // a[i]为原始数组 //= sigma( a[x] ) + sigma( delta[x] * (i + 1 - x) ) //= sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x ) #include<bits/stdc++.h> using namespace std; const int N=200100; int n; long long sum[N];//原始数组前缀和 long long delta[N];//差分数组 long long deltai[N];//delta[x]*i inline int lowbit(int x) {return x&(-x);} void add(long long *c,int a,int b) { while(a<=n) { c[a]+=b; a+=lowbit(a); } } long long query(long long *c,int a) { long long s=0; while(a) { s+=c[a]; a-=lowbit(a); } return s; } int main() { freopen("a.in","r",stdin); scanf("%d",&n); int a; for(int i=1;i<=n;i++) scanf("%d",&a),sum[i]=sum[i-1]+a; int m,l,r,x; scanf("%d",&m); long long suml,sumr; for(int i=1;i<=m;i++) { scanf("%d",&a); if(a==1) { scanf("%d%d%d",&l,&r,&x); add(delta,l,x);add(delta,r+1,-x); add(deltai,l,x*l);add(deltai,r+1,-x*(r+1)); } else { scanf("%d%d",&l,&r); suml=sum[l-1]+l*query(delta,l-1)-query(deltai,l-1); sumr=sum[r]+(r+1)*query(delta,r)-query(deltai,r); printf("%lld\n",sumr-suml); } } return 0; }
以上是关于树状数组的区间修改与区间查修的主要内容,如果未能解决你的问题,请参考以下文章