板子:(秋实大哥与花)
线段树要开四倍空间,
push_down中的lazy操作,简言之,更新到一个区间时,按照updata就一直更新下去,而如果在这个区间内的话,直接打lazy标记更新区间,而没必要updata下去;
#include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> const int N=500000; typedef long long LL; typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200001 #define mod 10007 #define eps 1e-9 //const int inf=0x7fffffff; //无限大 const int inf=0x3f3f3f3f; int n,m; int a[maxn]; struct node{ int l,r; long long sum,lazy; void update(long long x) { sum+=1ll*(r-l+1)*x; lazy+=x; } }tree[maxn*4]; void push_up(int x)//自下而上 { tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum; } void push_down(int x)//自上而下 { int lazyval=tree[x].lazy; if(lazyval) { tree[x<<1].update(lazyval); tree[x<<1|1].update(lazyval);//这里x<<1|1=x*2+1 tree[x].lazy=0;//一定要清除掉 } } void build(int x,int l,int r)//x即为root(根节点) { tree[x].l=l,tree[x].r=r; tree[x].sum=tree[x].lazy=0;//初始化 if(l==r) tree[x].sum=a[l]; else { int mid=(l+r)/2; build(x<<1,l,mid);//左子树 build(x<<1|1,mid+1,r);//右子树 push_up(x);//更新sum值 } } void update(int x,int l,int r,long long val) { int L=tree[x].l,R=tree[x].r; if(l<=L&&R<=r)//保证在区间内 tree[x].update(val); else { push_down(x); int mid=(L+R)/2; if(mid>=l) update(x<<1,l,r,val);//链状更新 if(r>mid) update(x<<1|1,l,r,val); push_up(x);//自下而上的更新sum } } long long quary(int x,int l,int r) { int L=tree[x].l,R=tree[x].r; if(l<=L&&R<=r) return tree[x].sum; else { push_down(x); long long ans=0; int mid=(L+R)/2; if(mid>=l) ans+=quary(x<<1,l,r); if(r>mid) ans+=quary(x<<1|1,l,r); push_up(x); return ans; } } int main() { while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; i++) scanf("%d",&a[i]); scanf("%d",&m); build(1,1,n); for(int i=1; i<=m; i++) { int l,r,val; scanf("%d%d%d",&l,&r,&val); update(1,l,r,val); printf("%lld ",quary(1,l,r)); } } return 0; }