浅谈 zkw 线段树
来源:互联网 发布:西安东华软件远古 编辑:程序博客网 时间:2024/06/04 19:51
这几天一直在看zkw版的线段树
他的常数极小 代码还很短 写起来不复杂 就是一开始比较难理解
较以往的线段树写法相差很多
下面浅谈下个人对zkw版的理解
首先呢 线段树就不用讲了
这样一颗线段树 如果我们把他的标号转换成2进制 是这个样子的
很显然 设深度为m 最后一层的点数是2^(m-1)
那么对于满二叉树 总结点数易知 是2^(m-1)*2-1个
那么神奇的地方来了
我们建树直接可以这样玩
void build(int n){ for(M=1;M<n;M<<=1); for(int i=1;i<=n;i++) cin>>tr[i+M];}
是不是很简单 什么意思呢 我们这相当于建了一个满二叉树 根节点编号是M+i 很显然没有建完 ,还需要一步
void build(int n){ for(M=1;M<n+2;M<<=1); for(int i=1;i<=n;i++) cin>>tr[i+M]; for(int i=M-1;i;i--) tr[i]=tr[i<<1]+tr[i<<|1]; }
这样我们就完成了建树
1.那么如何单点修改呢?
void modify(int x,int k){ tr[x+=M]+=k; while(x) tr[x>>=1]=tr[x<<1]+tr[x<<1|1];}
2 如何 单点查询呢?
最朴素的做法
int query(int x){ return tr[x+M];}
3好了 区间和呢?
int sum(int s,int t){ int ans=0; for(s+=M-1,t+=M+1;s^t^1;s>>=1;t>>=1) { if(~s&1) ans+=tr[s^1]; if(t&1) ans+=tr[t^1]; } return ans;}
为什么 要这样写呢
我们转换成开区间后
易知 在未超过边界的情况下 若s为左儿子 那么他的兄弟一定正在查询范围内 同理t为右儿子 他兄弟也在查询范围内
那么我们就可以去维护他兄弟的值了 如此可避免重复
4区间最大最小值呢
这个时候 我们不妨改一下 存取方式 换成 差分的做法
为什么要换成差分做呢 因为这样单点话我们维护起来会更快
此时我们建树 及单点查询
void build(int n){ for(M=1;M<n+2;M<<=1); for(int i=1;i<=n;i++) cin>>tr[i+M], tr[i<<1]-=tr[i],tr[i<<1|1]-=tr[i];}int query(int x){ int ans=tr[x+=M]; while(x) ans+=tr[x>>=1]; return ans;}
这里就暂时先不介绍区间了 比较难记 以后再补上
阅读全文
0 0
- 浅谈ZKW线段树
- 浅谈 zkw 线段树
- zkw线段树 运用
- 【zkw线段树】ural1855
- ZKW线段树
- POJ3468 ZKW线段树
- ZKW线段树
- zkw线段树 模板
- ZKW线段树
- zkw线段树
- zkw线段树
- zkw线段树分析
- ZKW 线段树
- zkw线段树
- zkw线段树详解
- zkw线段树
- poj3468 zkw线段树
- zkw线段树
- 数学建模多元分析实例
- 消除重复元素--网易2017春招实习笔试编程题4
- 常见的线程调度模型
- 伪静态
- vue.js学习笔记-8
- 浅谈 zkw 线段树
- java之dbutils笔记
- 读取图片路径,显示图片
- 浅谈SQL SERVER中事务的ACID
- Copying Books--(二分)
- S动态修改页面EasyUI datebox不生效、EasyUI动态添加Cla
- postgresql-pg_stat_statements
- Android WebView加载本地文件,使用JavaScript定位到指定位置
- HDU6103 Kirinriki-dp+二分