C02【模板】线段树+懒标记 P3372 线段树 1
C02【模板】线段树+懒标记 P3372 线段树——信息学竞赛算法_哔哩哔哩_bilibili
给一个序列,两种操作:区间加,区间和。
线段树是常用的维护 区间信息 的数据结构
线段树可以在 $O(logN)$ 的时间复杂度内实现 单点修改、区间修改、区间查询(区间求和,求区间最值)等操作
1. 序列元素 映射为 线段树的叶节点
2. 节点信息:lc rc mid, sum[], add[]
3. 上传;下传;建树;区修;区查
4. 覆盖即返回,延迟修改
// 线段树 O(mlogn) 数组版 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) #define mid (l+r>>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 m){ if(add[u]){ sum[lc]+=add[u]*(m-l+1); sum[rc]+=add[u]*(r-m); add[lc]+=add[u]; add[rc]+=add[u]; add[u]=0; } } void build(int u=1,int l=1,int r=n){ if(l==r){sum[u]=w[l]; return;} build(lc,l,mid); build(rc,mid+1,r); pushup(u); } void upd(int x,int y,int k,int u=1,int l=1,int r=n){ //区修 if(x>r || y<l) return; //越界 if(x<=l && r<=y){ //覆盖即返回 sum[u]+=(r-l+1)*k; add[u]+=k; return; } pushdown(u,l,r,mid); upd(x,y,k,lc,l,mid); //裂开 upd(x,y,k,rc,mid+1,r); pushup(u); } int ask(int x,int y,int u=1,int l=1,int r=n){ //区查 if(x>r || y<l) return 0; if(x<=l && r<=y) return sum[u]; pushdown(u,l,r,mid); return ask(x,y,lc,l,mid)+ask(x,y,rc,mid+1,r); } }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(); while(m--){ cin>>op>>x>>y; if(op==1) cin>>k,S.upd(x,y,k); else cout<<S.ask(x,y)<<"\n"; } }
// 结构体版 #include<bits/stdc++.h> using namespace std; #define int long long #define N 100005 int n,m,w[N]; struct SGT{ //线段树 #define lc (u<<1) #define rc (u<<1|1) #define mid (l+r>>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=1,int l=1,int r=n){ //建树 tr[u]={l,r,w[l],0}; if(l==r) return; build(lc,l,mid); build(rc,mid+1,r); pushup(u); } void upd(int x,int y,int k,int u=1){ //区修 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); upd(x,y,k,lc); upd(x,y,k,rc); pushup(u); } int ask(int x,int y,int u=1){ //区查 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 ask(x,y,lc)+ask(x,y,rc); } }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(); for(int op,x,y,k; m--;){ cin>>op>>x>>y; if(op==1) cin>>k,S.upd(x,y,k); else cout<<S.ask(x,y)<<"\n"; } }
P3374 【模板】树状数组 1 - 洛谷
#include<bits/stdc++.h> 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<bits/stdc++.h> 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号