C02【模板】线段树+懒标记 P3372 线段树 1
视频链接:C02【模板】线段树+懒标记 P3372 线段树——信息学竞赛算法_哔哩哔哩_bilibili
1. 序列→线段树
2. 节点信息:sum[u],add[u]
3. 上传;下传;建树;区修;区查
4. 裂开 lc rc mid;延迟修改
// 数组版 I LOVE #include<bits/stdc++.h> using namespace std; #define int long long #define N 100005 int n,m,w[N],op,x,y,k; struct SGT{ #define lc u<<1 #define rc u<<1|1 int sum[N*4],add[N*4]; //区间和,懒标记 void pushup(int u){ sum[u]=sum[lc]+sum[rc]; } void pushdown(int u,int l,int r,int mid){ if(add[u]){ sum[lc]+=add[u]*(mid-l+1); sum[rc]+=add[u]*(r-mid); add[lc]+=add[u]; add[rc]+=add[u]; add[u]=0; } } void build(int u,int l,int r){ if(l==r){sum[u]=w[l]; return;} int mid=l+r>>1; build(lc,l,mid); build(rc,mid+1,r); pushup(u); } void change(int u,int l,int r,int x,int y,int k){ //区修 if(x>r || y<l) return; //越界 if(x<=l && r<=y){ //覆盖 sum[u]+=(r-l+1)*k; add[u]+=k; return; } int mid=l+r>>1; pushdown(u,l,r,mid); change(lc,l,mid,x,y,k); //裂开 change(rc,mid+1,r,x,y,k); pushup(u); } int query(int u,int l,int r,int x,int y){ //区查 if(x>r || y<l) return 0; if(x<=l && r<=y) return sum[u]; int mid=l+r>>1; pushdown(u,l,r,mid); return query(lc,l,mid,x,y)+query(rc,mid+1,r,x,y); } }S; signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>m; for(int i=1; i<=n; i++) cin>>w[i]; S.build(1,1,n); while(m--){ cin>>op>>x>>y; if(op==1) cin>>k,S.change(1,1,n,x,y,k); else cout<<S.query(1,1,n,x,y)<<"\n"; } }
// 结构体版 #include<bits/stdc++.h> using namespace std; #define int long long #define N 100005 int n,m,w[N],op,x,y,k; struct SGT{ #define lc u<<1 #define rc u<<1|1 struct sgt{ int l,r,sum,add; }tr[N*4]; void pushup(int u){ //上传 tr[u].sum=tr[lc].sum+tr[rc].sum; } void pushdown(int u){ //下传 if(tr[u].add){ tr[lc].sum+=tr[u].add*(tr[lc].r-tr[lc].l+1), tr[rc].sum+=tr[u].add*(tr[rc].r-tr[rc].l+1), tr[lc].add+=tr[u].add, tr[rc].add+=tr[u].add, tr[u].add=0; } } void build(int u,int l,int r){ //建树 tr[u]={l,r,w[l],0}; if(l==r) return; int m=l+r>>1; build(lc,l,m); build(rc,m+1,r); pushup(u); } void change(int u,int x,int y,int k){ //区修 if(x>tr[u].r || y<tr[u].l) return; if(x<=tr[u].l && tr[u].r<=y){ tr[u].sum+=(tr[u].r-tr[u].l+1)*k; tr[u].add+=k; return; } pushdown(u); change(lc,x,y,k); change(rc,x,y,k); pushup(u); } int query(int u,int x,int y){ //区查 if(x>tr[u].r || y<tr[u].l) return 0; if(x<=tr[u].l && tr[u].r<=y) return tr[u].sum; pushdown(u); return query(lc,x,y)+query(rc,x,y); } }S; signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n,m,op,x,y,k; cin>>n>>m; for(int i=1; i<=n; i ++) cin>>w[i]; S.build(1,1,n); while(m--){ cin>>op>>x>>y; if(op==1)cin>>k,S.change(1,x,y,k); else cout<<S.query(1,x,y)<<"\n"; } }
P3374 【模板】树状数组 1 - 洛谷
#include <cstring> #include <iostream> #include <algorithm> using namespace std; #define lc u<<1 #define rc u<<1|1 #define N 500005 int w[N]; struct Tree{ int l,r,sum; }tr[N*4]; void pushup(int u){ //上传 tr[u].sum=tr[lc].sum+tr[rc].sum; } void build(int u,int l,int r){ tr[u]={l,r,w[l]}; if(l==r) return; int m=l+r>>1; build(lc,l,m); build(rc,m+1,r); pushup(u); } void change(int u,int x,int k){ //点修 if(tr[u].l==x&&tr[u].r==x){ tr[u].sum+=k; return; } int m=tr[u].l+tr[u].r>>1; if(x<=m) change(lc,x,k); if(x>m) change(rc,x,k); pushup(u); } int query(int u,int l,int r){ //区查 if(l>tr[u].r || r<tr[u].l) return 0; if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum; return query(lc,l,r)+query(rc,l,r); } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n,m,op,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]; build(1,1,n); while(m--){ cin>>op>>x>>y; if(op==1) change(1,x,y); else cout<<query(1,x,y)<<endl; } return 0; }
P3368 【模板】树状数组 2 - 洛谷
#include <cstring> #include <iostream> #include <algorithm> using namespace std; #define N 500005 #define LL long long #define lc u<<1 #define rc u<<1|1 LL w[N]; struct Tree{ //线段树 LL l,r,sum,add; }tr[N*4]; void pushup(LL u){ //上传 tr[u].sum=tr[lc].sum+tr[rc].sum; } void pushdown(LL u){ //下传 if(tr[u].add){ tr[lc].sum+=tr[u].add*(tr[lc].r-tr[lc].l+1), tr[rc].sum+=tr[u].add*(tr[rc].r-tr[rc].l+1), tr[lc].add+=tr[u].add, tr[rc].add+=tr[u].add, tr[u].add=0; } } void build(LL u,LL l,LL r){ //建树 tr[u]={l,r,w[l],0}; if(l==r) return; LL m=l+r>>1; build(lc,l,m); build(rc,m+1,r); pushup(u); } void change(LL u,LL x,LL y,LL k){ //区修 if(x>tr[u].r || y<tr[u].l) return; if(x<=tr[u].l && tr[u].r<=y){ tr[u].sum+=(tr[u].r-tr[u].l+1)*k; tr[u].add+=k; return; } pushdown(u); change(lc,x,y,k); change(rc,x,y,k); pushup(u); } LL query(LL u,LL x){ //点查 if(x>tr[u].r || x<tr[u].l) return 0; if(x==tr[u].l && tr[u].r==x) return tr[u].sum; pushdown(u); return query(lc,x)+query(rc,x); } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n,m,op,x,y,k; cin>>n>>m; for(int i=1; i<=n; i ++) cin>>w[i]; build(1,1,n); while(m--){ cin>>op>>x; if(op==2)cout<<query(1,x)<<endl; else cin>>y>>k,change(1,x,y,k); } return 0; }
Luogu P2846 [USACO08NOV] Light Switching G
Luogu P2894 [USACO08FEB] Hotel G
浙公网安备 33010602011771号