线段树
目录
L如果你害怕失敗,那你很有可能會失敗。 If you’re afraid to fail, then you’re probably going to fail.
线段树模版
#include <iostream>
using namespace std;
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _for(i,a,b) for(int i=(a);i<(b);++i)
inline int readint(){int x;scanf("%d",&x);return x;}
const int MAXN=1e5 +10;
long long sum[4*MAXN];
long long add[4*MAXN];//add是lazy标签
int t,n,m;
void push_up(int rt){//向上更新
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void push_down(int rt,int m){
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=(m-(m>>1))*add[rt];
sum[rt<<1|1]+=(m>>1)*add[rt];
//向下更新
add[rt]=0;
}
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void build(int l,int r,int rt){
add[rt]=0;
if(l==r){
scanf("%lld",&sum[rt]);
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);//建树到最底层 退出递归到倒数第二层 向下跟新一层 在退出一层 再向下更新一层 完成向上更新区间和
push_up(rt);
}
void update(int a,int b,long long c,int l,int r,int rt){
if(a<=l && b>=r){
sum[rt]+=(r-l+1)*c;//更新区间和
add[rt]+=c;//添加lazy标记
return;
}
push_down(rt,r-l+1);//向下更新被修改的区间
int mid=(l+r)>>1;
if(a<=mid) update(a,b,c,lson);
if(b>mid) update(a,b,c,rson);
push_up(rt);
}
long long query(int a,int b,int l,int r,int rt){
if(a<=l && b>=r) return sum[rt];//被查找区间 已经包含
//没有被包含 需要访问下面的 所以向下更新
push_down(rt,r-l+1);
int mid=(l+r)>>1;
long long ans=0;
if(a<=mid) ans+=query(a,b,lson);
if(b>mid) ans+=query(a,b,rson);
return ans;
}
int main(){
t=readint();
while(t--){
n=readint();
build(1,n,1);
m=readint();
while(m--){
int l=readint();
int r=readint();
int x=readint();
update(l,r,x,1,n,1);
}
_rep(i,1,n) if(i!=n) cout<<query(i,i,1,n,1)<<" ";else cout<<query(i,i,1,n,1)<<endl;
}
return 0;
}