设原数组为:
记录其查分序列:
此时有:
那么原数组的前缀和变为:
维护一个辅助数组cc:
那么原数组前缀和变成:
区间查询就可以实现了,接下来是区间更新
如果我需要对[L,R]区间的数加上V,只需要利用查分序列修改两端的值即可
例题
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define debug(i) printf("# %d\n",i)
#define pill pair<int,int>
const LL mod = 998244353;
const int N = 200005;
LL a[N];
LL c[N],cc[N];
void add(LL* tr,int pos,LL v,int n){
while(pos<=n)tr[pos]+=v,pos+=pos&-pos;
}
LL query(LL* tr,int pos){
LL ans=0;
while(pos)ans+=tr[pos],pos-=pos&-pos;
return ans;
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
}
for(int i=1;i<=n;i++)add(c,i,a[i]-a[i-1],n),add(cc,i,(i-1)*(a[i]-a[i-1]),n);
int q;scanf("%d",&q);
while(q--){
int op,l,r;scanf("%d%d%d",&op,&l,&r);
if(op==1){
LL v;
scanf("%lld",&v);
add(c,l,v,n);
add(c,r+1,-v,n);
add(cc,l,(l-1)*v,n);
add(cc,r+1,-r*v,n);
}
else{
printf("%lld\n",r*query(c,r)-query(cc,r)-((l-1)*query(c,l-1)-query(cc,l-1)));
}
}
}