| [线段树] |
| 本质为二叉树 |
| 用来区间查询,区间修改, |
| 单点查询,单点修改 |
| 运用结构体存储。 |
| struct node{ |
| int sum,laze; |
| }tree[N*4]; |
| |
| void build_tree(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return; |
| } |
| int mid=(l+r)/2; |
| build_tree(id*2,l,mid); |
| build_tree(id*2+1,mid+1,r); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| |
| int query(int id,int l,int r,int fl,int fr){ |
| if(l==fl&&r==fr){ |
| return tree[id].sum; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return query(id*2,l,mid,fl,mid) |
| +query(id*2+1,mid+1,r,mid+1,fr); |
| } |
| } |
| |
| void change_one(int id,int l,int r,int fn,int cs){ |
| if(l==r){ |
| tree[id].sum+=cs; |
| return ; |
| } |
| int mid=(l+r)/2; |
| if(fn<=mid)change_one(id*2,l,mid,fn,cs); |
| else change_one(id*2+1,mid+1,r,fn,cs); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| |
| void pushup(int id){ |
| tree[id].sum=tree[id*2].sum+t[id*2+1].sum; |
| } |
| void pushdown(int id,int l,int r){ |
| if(tree[id].laze){ |
| int mid=(l+r)/2; |
| put_tag(id*2,l,mid,tree[id].laze); |
| put_tag(id*2+1,mid+1,r,tree[id].laze); |
| tree[id].laze=0; |
| } |
| } |
| void put_tag(int id,int l,int r,int val){ |
| tree[id].sum+=1ll*(r-l+1)*val; |
| tree[id].laze+=val; |
| } |
| |
| long long query(int id,int l,int r,int fl,int fr){ |
| if(fl==l&&fr==r){ |
| return tree[id].sum; |
| } |
| pushdown(id,l,r); |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return query(id*2,l,mid,fl,mid) |
| +query(id*2+1,mid+1,r,mid+1,fr); |
| } |
| } |
| |
| void change(int id,int l,int r,int fl,int fr,long long val){ |
| if(fl==l&&fr==r){ |
| put_tag(id,l,r,val); |
| return ; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| change(id*2,l,mid,fl,fr,val); |
| }else if(fl>mid){ |
| change(id*2+1,mid+1,r,fl,fr,val); |
| }else{ |
| change(id*2,l,mid,fl,mid,val); |
| change(id*2+1,mid+1,r,mid+1,fr,val); |
| } |
| pushup(id); |
| } |
| 1. |
| accoders线段树 区间最小 |
| 思路: |
| 区间查询最小值,把return query(id*2,l,mid,fl,mid)+query(id*2+1,mid+1,r,mid+1,fr); |
| 改为min(query(id*2,l,mid,fl,mid),query(id*2+1,mid+1,r,mid+1,fr)); |
| 即可 。 |
| code: |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=1e5+10; |
| int n,m; |
| int a[N]; |
| struct node{ |
| int sum,laze; |
| }tree[N*4]; |
| void build(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return ; |
| } |
| int mid=(l+r)/2; |
| build(id*2,l,mid); |
| build(id*2+1,mid+1,r); |
| tree[id].sum=min(tree[id*2].sum,tree[id*2+1].sum); |
| } |
| int query(int id,int l,int r,int fl,int fr){ |
| if(fl==l&&fr==r){ |
| return tree[id].sum; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return min(query(id*2,l,mid,fl,mid),query(id*2+1,mid+1,r,mid+1,fr)); |
| } |
| } |
| int main(){ |
| ios::sync_with_stdio(0); |
| cin.tie(0); |
| cout.tie(0); |
| cin>>n>>m; |
| for(int i=1;i<=n;i++){ |
| cin>>a[i]; |
| } |
| build(1,1,n); |
| for(int i=1;i<=m;i++){ |
| int x,y; |
| cin>>x>>y; |
| cout<<query(1,1,n,x,y)<<" "; |
| } |
| return 0; |
| } |
| 2. |
| accoders线段树 带修改的区间最小 |
| 思路: |
| 加上单点修改即可,将tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| 改为 tree[id].sum=min(tree[id*2].sum,tree[id*2+1].sum); |
| 即可。 |
| code: |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=1e5+10; |
| int n,m; |
| int a[N]; |
| struct node{ |
| int sum,laze; |
| }tree[N*4]; |
| void build(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return ; |
| } |
| int mid=(l+r)/2; |
| build(id*2,l,mid); |
| build(id*2+1,mid+1,r); |
| tree[id].sum=min(tree[id*2].sum,tree[id*2+1].sum); |
| } |
| int query(int id,int l,int r,int fl,int fr){ |
| if(fl==l&&fr==r){ |
| return tree[id].sum; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return min(query(id*2,l,mid,fl,mid),query(id*2+1,mid+1,r,mid+1,fr)); |
| } |
| } |
| void change(int id,int l,int r,int fn,int val){ |
| if(l==r){ |
| tree[id].sum=val; |
| return ; |
| } |
| int mid=(l+r)/2; |
| if(fn<=mid){ |
| change(id*2,l,mid,fn,val); |
| }else{ |
| change(id*2+1,mid+1,r,fn,val); |
| } |
| tree[id].sum=min(tree[id*2].sum,tree[id*2+1].sum); |
| } |
| int main(){ |
| ios::sync_with_stdio(0); |
| cin.tie(0); |
| cout.tie(0); |
| cin>>n>>m; |
| for(int i=1;i<=n;i++){ |
| cin>>a[i]; |
| } |
| build(1,1,n); |
| for(int i=1;i<=m;i++){ |
| int f; |
| cin>>f; |
| if(f==1){ |
| int x,y; |
| cin>>x>>y; |
| cout<<query(1,1,n,x,y)<<" "; |
| }else{ |
| int x,y; |
| cin>>x>>y; |
| change(1,1,n,x,y); |
| } |
| } |
| return 0; |
| } |
| 3. |
| luogu P3374 【模板】树状数组1 |
| 什么,你问为什么树状数组的题要用线段树写? |
| (别问(划掉)) |
| 因为他的区间查询正好是线段树能解决的,也是线段树的弱化版,适合练手。 |
| 思路: |
| 考察区间加和区间和,套板子即可。 |
| 注: |
| 要开long long。 |
| code: |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=5e5+10; |
| int a[N]; |
| struct node{ |
| long long sum,laze; |
| }tree[N*4]; |
| void build_tree(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return; |
| } |
| int mid=(l+r)/2; |
| build_tree(id*2,l,mid); |
| build_tree(id*2+1,mid+1,r); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| int query(int id,int l,int r,int fl,int fr){ |
| if(l==fl&&r==fr){ |
| return tree[id].sum; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return query(id*2,l,mid,fl,mid) |
| +query(id*2+1,mid+1,r,mid+1,fr); |
| } |
| } |
| void change_one(int id,int l,int r,int fn,int cs){ |
| if(l==r){ |
| tree[id].sum+=cs; |
| return ; |
| } |
| int mid=(l+r)/2; |
| if(fn<=mid)change_one(id*2,l,mid,fn,cs); |
| else change_one(id*2+1,mid+1,r,fn,cs); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| int main(){ |
| int n,m; |
| cin>>n>>m; |
| for(int i=1;i<=n;i++){ |
| cin>>a[i]; |
| } |
| build_tree(1,1,n); |
| for(int i=1;i<=m;i++){ |
| int f,x,y; |
| cin>>f>>x>>y; |
| if(f==1){ |
| change_one(1,1,n,x,y); |
| }else{ |
| cout<<query(1,1,n,x,y)<<"\n"; |
| } |
| } |
| return 0; |
| } |
| 4. |
| luogu P3368 【模板】树状数组 2 |
| 来都来了,直接(水(划掉))做完好了。 |
| 思路: |
| 区间加和单点查,要用到laze了。 |
| code: |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=5e5+10; |
| int a[N]; |
| struct node{ |
| int sum,laze; |
| }tree[N*4]; |
| void pushup(int id){ |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| void put_tag(int id,int l,int r,int val){ |
| tree[id].sum+=1ll*(r-l+1)*val; |
| tree[id].laze+=val; |
| } |
| void pushdown(int id,int l,int r){ |
| if(tree[id].laze){ |
| int mid=(l+r)/2; |
| put_tag(id*2,l,mid,tree[id].laze); |
| put_tag(id*2+1,mid+1,r,tree[id].laze); |
| tree[id].laze=0; |
| } |
| } |
| void build(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return ; |
| } |
| int mid=(l+r)/2; |
| build(id*2,l,mid); |
| build(id*2+1,mid+1,r); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| long long query(int id,int l,int r,int fl,int fr){ |
| if(fl==l&&fr==r){ |
| return tree[id].sum; |
| } |
| pushdown(id,l,r); |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return query(id*2,l,mid,fl,mid) |
| +query(id*2+1,mid+1,r,mid+1,fr); |
| } |
| } |
| void change(int id,int l,int r,int fl,int fr,long long val){ |
| if(fl==l&&fr==r){ |
| put_tag(id,l,r,val); |
| return ; |
| } |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| change(id*2,l,mid,fl,fr,val); |
| }else if(fl>mid){ |
| change(id*2+1,mid+1,r,fl,fr,val); |
| }else{ |
| change(id*2,l,mid,fl,mid,val); |
| change(id*2+1,mid+1,r,mid+1,fr,val); |
| } |
| pushup(id); |
| } |
| int main(){ |
| int n,m; |
| cin>>n>>m; |
| for(int i=1;i<=n;i++){ |
| cin>>a[i]; |
| } |
| build(1,1,n); |
| for(int i=1;i<=m;i++){ |
| int f; |
| cin>>f; |
| if(f==1){ |
| int x,y,k; |
| cin>>x>>y>>k; |
| change(1,1,n,x,y,k); |
| }else{ |
| int x; |
| cin>>x; |
| cout<<query(1,1,n,x,x)<<"\n"; |
| } |
| } |
| return 0; |
| } |
| 5. |
| luogu P3372 【模板】线段树 1 |
| 终于是做上线段树的题了。 |
| 思路: |
| 区间加和区间查。 |
| code: |
| #include<bits/stdc++.h> |
| #define int long long |
| using namespace std; |
| const int N=5e5+10; |
| int a[N]; |
| struct node{ |
| int sum,laze; |
| }tree[N*4]; |
| void pushup(int id){ |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| void put_tag(int id,int l,int r,int val){ |
| tree[id].sum+=1ll*(r-l+1)*val; |
| tree[id].laze+=val; |
| } |
| void pushdown(int id,int l,int r){ |
| if(tree[id].laze){ |
| int mid=(l+r)/2; |
| put_tag(id*2,l,mid,tree[id].laze); |
| put_tag(id*2+1,mid+1,r,tree[id].laze); |
| tree[id].laze=0; |
| } |
| } |
| void build(int id,int l,int r){ |
| if(l==r){ |
| tree[id].sum=a[l]; |
| return; |
| } |
| int mid=(l+r)/2; |
| build(id*2,l,mid); |
| build(id*2+1,mid+1,r); |
| tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; |
| } |
| long long query(int id,int l,int r,int fl,int fr){ |
| if(fl==l&&fr==r){ |
| return tree[id].sum; |
| } |
| pushdown(id,l,r); |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| return query(id*2,l,mid,fl,fr); |
| }else if(fl>mid){ |
| return query(id*2+1,mid+1,r,fl,fr); |
| }else{ |
| return query(id*2,l,mid,fl,mid) |
| +query(id*2+1,mid+1,r,mid+1,fr); |
| } |
| } |
| void change(int id,int l,int r,int fl,int fr,long long val){ |
| if(fl==l&&fr==r){ |
| put_tag(id,l,r,val); |
| return ; |
| } |
| pushdown(id,l,r); |
| int mid=(l+r)/2; |
| if(fr<=mid){ |
| change(id*2,l,mid,fl,fr,val); |
| }else if(fl>mid){ |
| change(id*2+1,mid+1,r,fl,fr,val); |
| }else{ |
| change(id*2,l,mid,fl,mid,val); |
| change(id*2+1,mid+1,r,mid+1,fr,val); |
| } |
| pushup(id); |
| } |
| signed main(){ |
| int n,m; |
| cin>>n>>m; |
| for(int i=1;i<=n;i++){ |
| cin>>a[i]; |
| } |
| build(1,1,n); |
| for(int i=1;i<=m;i++){ |
| int f; |
| cin>>f; |
| if(f==1){ |
| int x,y,k; |
| cin>>x>>y>>k; |
| change(1,1,n,x,y,k); |
| }else{ |
| int x,y; |
| cin>>x>>y; |
| cout<<query(1,1,n,x,y)<<"\n"; |
| } |
| } |
| return 0; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效