线段树进阶之模板观见
——————————————————————已识乾坤大,犹怜草木青。
先介绍一篇优秀的洛谷博文:https://www.luogu.org/problemnew/solution/P3372
-----------------------------------------------------------------------------------------------------------------------------------------------
lazy tag:
皎月半酒花说:
首先,懒标记(lazy tag)的作用是记录每次、每个节点要更新的值,也就是delta,但线段树的优点不在于全记录,而在于传递式记录:
整个区间都被操作,记录在公共祖先节点上;只修改了一部分,那么就记录在这部分的公共祖先上;如果四环以内只修改了自己的话,那就只改变自己。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题目见此:https://www.luogu.org/problem/P3372
#include<iostream> #include<cstdio> #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; } void scan() { cin>>n>>m; for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); } inline void push_up(ll p) { ans[p]=ans[ls(p)]+ans[rs(p)]; } void build(ll p,ll l,ll r) { tag[p]=0; if(l==r){ans[p]=a[l];return ;} ll mid=(l+r)>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } inline void f(ll p,ll l,ll r,ll k) { tag[p]=tag[p]+k; ans[p]=ans[p]+k*(r-l+1); } inline void push_down(ll p,ll l,ll r) { ll mid=(l+r)>>1; f(ls(p),l,mid,tag[p]); f(rs(p),mid+1,r,tag[p]); tag[p]=0; } inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k) { if(nl<=l&&r<=nr) { ans[p]+=k*(r-l+1); tag[p]+=k; return ; } push_down(p,l,r); ll mid=(l+r)>>1; if(nl<=mid)update(nl,nr,l,mid,ls(p),k); if(nr>mid) update(nl,nr,mid+1,r,rs(p),k); push_up(p); } ll query(ll q_x,ll q_y,ll l,ll r,ll p) { ll res=0; if(q_x<=l&&r<=q_y)return ans[p]; ll mid=(l+r)>>1; push_down(p,l,r); if(q_x<=mid)res+=query(q_x,q_y,l,mid,ls(p)); if(q_y>mid) res+=query(q_x,q_y,mid+1,r,rs(p)); return res; } int main() { ll a1,b,c,d,e,f; scan(); build(1,1,n); while(m--) { scanf("%lld",&a1); switch(a1) { case 1:{ scanf("%lld%lld%lld",&b,&c,&d); update(b,c,1,n,1,d); break; } case 2:{ scanf("%lld%lld",&e,&f); printf("%lld\n",query(e,f,1,n,1)); break; } } } return 0; }
相关函数的熟悉可以以此当做模板样子丫!
建树,区间修改,区间查询这样的函数当每日三省,无比熟稔之!