C79【模板】线段树+标记永久化 区修+区查 Luogu P3372 线段树 1
C79 线段树+标记永久化 区修+区查 Luogu P3372 线段树 1_哔哩哔哩_bilibili
标记永久化
修改时留下的懒标记(tag)并不下传,也不删除,而是留在打上标记的那一个节点上
当查询经过这个节点时,就加上这个节点的懒标记造成的影响
标记永久化 不需要 pushdown 和 pushup


相关板子:
C02【模板】线段树+懒标记 P3372 线段树 1 - 董晓 - 博客园
// 线段树+标记永久化 O(M*logN) #include<bits/stdc++.h> #define LL long long using namespace std; const int N=100005; int n,m; LL a[N]; struct SGT{ //线段树 #define ls u<<1 #define rs u<<1|1 #define mid ((l+r)>>1) LL sum[N*4],tag[N*4]; //区间和,永久标记 void build(int u=1,int l=1,int r=n){ //建树 sum[u]=a[l]; if(l==r) return; build(ls,l,mid); build(rs,mid+1,r); sum[u]=sum[ls]+sum[rs]; } void upd(int x,int y,LL k,int u=1,int l=1,int r=n){ //区修 sum[u]+=(min(r,y)-max(x,l)+1)*k; //经过节点更新sum if(x<=l&&r<=y){tag[u]+=k;return;} //覆盖节点更新tag if(x<=mid) upd(x,y,k,ls,l,mid); if(y>mid) upd(x,y,k,rs,mid+1,r); } LL ask(int x,int y,LL s,int u=1,int l=1,int r=n){ //区查 if(x<=l&&r<=y)return sum[u]+(min(r,y)-max(x,l)+1)*s; //覆盖即返回 LL res=0; s+=tag[u]; //累计标记,下传给儿子 if(x<=mid) res+=ask(x,y,s,ls,l,mid); if(y>mid) res+=ask(x,y,s,rs,mid+1,r); return res; } }T; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); T.build(); int op,x,y; LL k; for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&x,&y); if(op==1) scanf("%lld",&k),T.upd(x,y,k); else printf("%lld\n",T.ask(x,y,0)); } }
浙公网安备 33010602011771号