#include <iostream> #define MAXN 1000001 #define ll long long using namespace std; unsigned ll n,m,a[MAXN],ans[MAXN<<2],tag[MAXN<<2]; inline ll ls(ll x){ return x<<1; } inline ll rs(ll x){ return x<<1|1; } inline void scan(){ scanf("%lld",&n); for(ll i =1;i<=n;i++) scanf("%lld",&a[i]); } inline void push_up(int k){ ans[k] = ans[ls(k)] + ans[rs(k)]; } void build(ll k,ll l,ll r){ tag[k]=0; if(l==r){ ans[k]=a[l]; return; } ll mid = (l + ((r-l)>>1)); build(ls(k),l,mid); build(rs(k),mid+1,r); push_up(k); } inline void f(int k,int l,int r,int c){ tag[k] += c;//标记更新 ans[k] += c*(r-l+1);//更新值 } inline void push_down(int k,int l,int r){ ll mid = (l+r)>>1; //开始从父结点传递标记给子结点 f(ls(k),l,mid,tag[k]); f(rs(k),mid+1,r,tag[k]); tag[k] = 0;//传递完后清空标记 } void update(ll k,ll tl,ll tr,ll l,ll r,ll c){//[tl,tr]目标区间,c 增加值 if(l>=tr&&r<=tl){ tag[k] += c;//延迟标记让更新在下一次修改或者查询的时候发生 ans[k] += c*(r-l+1); return; } push_down(k,l,r); ll mid = (l+r)<<1; if(l<=mid) update(ls(k),tl,tr,l,mid,c); if(r>mid) update(rs(k),tl,tr,mid+1,r,c); push_up(k); } ll query(ll k,ll tl,ll tr,ll l,ll r){ ll res = 0; if(l>=tl&&r<=tr){ return ans[k]; } ll mid = (l+r)<<1; push_down(k,l,r); if(l<=mid) res += query(ls(k),tl,tr,l,mid); if(r>mid) res += query(rs(k),tl,tr,mid+1,r); return res; } int main(){ scan(); build(1,1,n); return 0; }
参考资料: