线段树区间修改+区间查询
来源:互联网 发布:伴奏制作软件 编辑:程序博客网 时间:2024/05/18 21:41
大致思路:
线段树的区间修改要比点修改难想一点。主要是多了一个延迟标记,目的是为了降低复杂度。但在询问的时候还需要把延迟标记逐个下放,还要更新原来的点,这就导致很难想了。
主要记住顺序:
- 要求区间修改
- 递归查找区间
- 发现现在区间完全属于需修改的区间,更新当前节点的信息,增加延迟标记。递归结束
- 若不完全属于则继续递归
- 询问区间
- 发现当前区间完全属于被查询区间,直接返回当前节点值
- 或者发现当前区间不完全属于被查询区间且当前节点有延迟标记,将延迟标记下放至叶节点,并更新叶节点信息。取消自身延迟标记。
- 继续递归
模板:
模板的情况是询问区间里的所有元素的和,修改是将区间的元素全部改成newp
#include<bits/stdc++.h>using namespace std;const int maxn=1e5+10;int a[maxn];int sum[maxn<<2],exc[maxn<<2];void maintain(int k){ sum[k]=sum[k<<1]+sum[k<<1|1];}void pushdown(int lenl,int lenr,int k)//标记下放,并更细节点信息{ if(exc[k]){ exc[k<<1]=exc[k]; exc[k<<1|1]=exc[k]; sum[k<<1]=exc[k]*lenl; sum[k<<1|1]=exc[k]*lenr; exc[k]=0; }}void build(int l,int r,int k){ if(l>r) return ; if(l==r){ sum[k]=a[l]; exc[k]=0; return ; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); maintain(k);}void change(int l,int r,int cl,int cr,int k,int newp){ if(l>r||cl>r||cr<l) return ; if(l>=cl&&r<=cr){ sum[k]=newp*(r-l+1);//在发现现在区域小于需要更新区域时 exc[k]=newp;//更新节点的结果,并增加延迟标记exc,用于之后的标记下放 return ; } int mid=(l+r)>>1; pushdown(mid-l+1,r-mid,k); change(l,mid,cl,cr,k<<1,newp); change(mid+1,r,cl,cr,k<<1|1,newp); maintain(k);}int query(int l,int r,int ql,int qr,int k){ if(l>r||ql>r||qr<l) return 0; if(l>=ql&&r<=qr) return sum[k]; int mid=(l+r)>>1,ans=0; pushdown(mid-l+1,r-mid,k);//每一层询问执行到这一步,为了下一次递归更新叶节点信息 if(mid>=l) ans+=query(l,mid,ql,qr,k<<1); if(mid<r) ans+=query(mid+1,r,ql,qr,k<<1|1); return ans;}int main(){ ios::sync_with_stdio(false); //freopen("in.txt","r",stdin); int n,m,cmd,l,r,newp; cin>>n; for(int i=1;i<=n;++i) cin>>a[i]; build(1,n,1); cin>>m; for(int i=0;i<m;++i){ cin>>cmd>>l>>r; if(cmd){ cin>>newp; change(1,n,l,r,1,newp); }else cout<<query(1,n,l,r,1)<<endl; } return 0;}
阅读全文
0 0
- 线段树区间修改+区间查询
- 线段树(区间修改,区间查询)
- [模板]-线段树-区间修改 + 区间查询
- [线段树][区间修改&&查询]
- 线段树 (区间修改 区间查询 延迟标记)
- 【洛谷】线段树 树状数组区间修改区间查询
- 【模板】线段树区间修改、区间求和、查询最值
- 线段树点修改 区间查询
- 【数据结构】【线段树】单点修改区间查询
- 线段树(单点修改,区间查询)
- 线段树(区间修改,单点查询)
- HDU1166 线段树 单点修改、区间查询
- 线段树区间修改
- 线段树区间修改
- 线段树区间修改
- 线段树区间查询
- 线段树模板 区间加减 区间修改
- 线段树(区间修改,区间求和)
- 8月4日总结
- 求区间中1的个数最多的数 若有多个输出最小的
- 临界判断&来回不间断切换效果的小算法
- Vue不同场景下组件间的数据交流
- 数据结构小结——顺序表(指针版)
- 线段树区间修改+区间查询
- java日期,时间比较
- 数据交换
- SPOJ VLATTICE
- gcc 和 nasm的区别
- Java 内存区域和GC机制
- 浅谈c++智能指针
- 【Node.js-2】自定义模块以及引用、自定义模块存放路径、发布升级自定义的模块
- 【NOIP2017】Day2