区间加,区间查询,改编版zkw,(原理基于zkw,把差分换成了pushDown),时间少,代码短,好写。
向上更新:
inline void pushUp(int x){
tree[x]=tree[x<<1]+tree[x<<1|1];
}
建树
void build(){
for(M=1;M<n+3;M<<=1);
for(register int i=1;i<=n;++i)scanf("%d",&tree[i+M]);
for(register int i=M;i<=(M<<1);++i)size[i]=1;
for(register int i=M-1;i;--i)size[i]=size[i<<1]+size[i<<1|1],pushUp(i);
}
单节点添加
inline void addNode(int x,int v){
adds[x]+=v;tree[x]+=size[x]*v;
}
从树根向下更新
void pushDown(int x){
if(x^1)pushDown(x>>1);
if(adds[x])addNode(x<<1,adds[x]),addNode(x<<1|1,adds[x]);
adds[x]=0;
}
区间加
void add(int l,int r,LL v){
pushDown((l+=M-1)>>1),pushDown((r+=M+1)>>1);
for(;l^r^1;l>>=1,r>>=1){
if(~l&1)addNode(l^1,v);if(r&1)addNode(r^1,v);
pushUp(l>>1),pushUp(r>>1);
}for(l>>=1;l;l>>=1)pushUp(l);
}
区间查询
LL query(int l,int r){LL ans=0;
pushDown((l+=M-1)>>1),pushDown((r+=M+1)>>1);
for(;l^r^1;l>>=1,r>>=1){
if(~l&1)ans+=tree[l^1];if(r&1)ans+=tree[r^1];
}return ans;
}
顺便附上模板代码,洛谷P3372:
#include<iostream>
#include<cstdio>
using namespace std;
#define LL long long
const int maxn = 1e5+5;
int n,m,M;
LL tree[maxn<<2],adds[maxn<<2],size[maxn<<2];
inline void pushUp(int x){
tree[x]=tree[x<<1]+tree[x<<1|1];
}
void build(){
for(M=1;M<n+3;M<<=1);
for(register int i=1;i<=n;++i)scanf("%d",&tree[i+M]);
for(register int i=M;i<=(M<<1);++i)size[i]=1;
for(register int i=M-1;i;--i)size[i]=size[i<<1]+size[i<<1|1],pushUp(i);
}
inline void addNode(int x,int v){
adds[x]+=v;tree[x]+=size[x]*v;
}
void pushDown(int x){
if(x^1)pushDown(x>>1);
if(adds[x])addNode(x<<1,adds[x]),addNode(x<<1|1,adds[x]);
adds[x]=0;
}
void add(int l,int r,LL v){
pushDown((l+=M-1)>>1),pushDown((r+=M+1)>>1);
for(;l^r^1;l>>=1,r>>=1){
if(~l&1)addNode(l^1,v);if(r&1)addNode(r^1,v);
pushUp(l>>1),pushUp(r>>1);
}for(l>>=1;l;l>>=1)pushUp(l);
}
LL query(int l,int r){LL ans=0;
pushDown((l+=M-1)>>1),pushDown((r+=M+1)>>1);
for(;l^r^1;l>>=1,r>>=1){
if(~l&1)ans+=tree[l^1];if(r&1)ans+=tree[r^1];
}return ans;
}
int main(){
int m;scanf("%d%d",&n,&m);
build();
while(m--){
int a,b,c,d;scanf("%d%d%d",&a,&b,&c);
if(b>c)swap(b,c);
if(a==1)scanf("%d",&d),add(b,c,d);
else printf("%lld\n",query(b,c));
}
}