zkw线段树学习笔记
zkw线段树学习笔记
今天模拟赛线段树被卡常了,由于我自带常数 \(buff\),所以学了下zkw线段树。
平常的线段树无论是修改还是查询,都是从根开始递归找到区间的,而zkw线段树直接从叶子结点开始操作。
建树
首先,我们需要把线段树补成一个堆形态的树,原序列在最后一层(最后一层的左右要留空,后面再讲为什么),这样一来,就可以轻松得出:原序列里第 \(x\) 个元素在线段树里的编号就是 \(x+2^k\) (其中 \(k\) 为线段树的深度,根节点深度为 \(0\) )
大概就是这样 :

不难发现最后一层节点掐头去尾,就是原序列编号加上二进制最高位上的 \(1\)。
代码实现也非常简单:
segment_tree(const int n = 0) {
for (M = 1; M - 2 < n; M <<= 1); //M是最后一层的节点个数
for (int i = 1; i <= n; ++i)
t[i + M] = in();
for (int i = M - 1; i; --i)
t[i] = t[i << 1] + t[i << 1 | 1]; //合并子树信息
}
单点查询
直接查
单点修改
。。直接上代码:
void update(int p) {
for (p += M; p; p >>= 1) t[p] += k;
}
区间操作
若当前操作区间为 \([x,y]\),可以把它先转为开区间 \((x-1,y+1)\) (最后一层左右要留空的原因),设此开区间左右端点在线段树的编号为 \(l,r\)。
\(l, r\) 同时向它们的父亲节点跳,若 \(l\) 是它父亲的左儿子,则它父亲的右儿子被操作( \(r\) 与 \(l\) 对称),直到 \(l,r\) 的父亲相同。
可以配合图片理解:

上图中:蓝色为 \(l,r\) 会跳到的点。因为查询区间为 \(l\) 右边和 \(r\) 左边组成的区间,当 \(l\) 为父亲的左儿子时,它父亲的右儿子一定在它左边( \(r\) 与 \(l\) 对称)。
区间修改、查询
这里以区间加法为例;
在普通的线段树中,一般用 \(lazy\) \(tag\) 来解决这个问题,zkw线段树同样可以,但从上向下操作、下放 \(lazy\) \(tag\) 等操作并不优雅 常数大。
可以采用标记永久化,随用随查,按zkw的说法——永久化的标记就是值。
考虑上文提到的区间操作的过程,自下向上走的过程中,根据遇到的标记来计算贡献。
具体实现细节可以看代码:
void modify(int l, int r, ll k) {
int lnum = 0, rnum = 0, now = 1;
//lnum 表示当前左端点走到的子树有多少个元素在修改区间内 (rnum与lnum对称)
//now 表示当前端点走到的这一层有多少个叶子节点
for (l = l + M - 1, r = r + M + 1; l ^ r ^ 1; l >>= 1, r >>= 1; now <<= 1) {
t[l] += k * lnum, t[r] += k * rnum;
if (~l & 1) t[l ^ 1] += k * now, add[l ^ 1] += k, lnum += now;
if (r & 1) t[r ^ 1] += k * now, add[r ^ 1] += k, rnum += now;
}
for (; l; l >>= 1, r >>= 1)
t[l] += k * lnum, t[r] += k * rnum;
}
long long query(int l, int r) {
int lnum = 0, rnum = 0, now = 1;
long long ret = 0;
for (l = l + M - 1, r = r + M + 1; l ^ r ^ 1; l >>= 1, r >>= 1, now <<= 1) {
if (add[l]) ret += add[l] * lnum;
if (add[r]) ret += add[r] * rnum;
if (~l & 1) ret += t[l ^ 1], lnum += now;
if (r & 1) ret += t[r ^ 1], rnum += now;
}
for (; l; l >>= 1, r >>= 1)
ret += add[l] * lnum, ret += add[r] * rnum;
return ret;
}
参考文献:《统计的力量》—— zkw
zkw线段树学习笔记的更多相关文章
- 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解
什么是线段树 线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值.区间和等问题. 线段树的用处 对编号连续的一些点进行修改或者统计操作,修改和统计的复杂度都是 O(log n). 基础 ...
- JSOI2008 Blue Mary开公司 | 李超线段树学习笔记
题目链接:戳我 这相当于是一个李超线段树的模板qwqwq,题解就不多说了. 代码如下: #include<iostream> #include<cstdio> #include ...
- 仙人掌&圆方树学习笔记
仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...
- 普及向 ZKW线段树!
啊,是否疲倦了现在的线段树 太弱,还递归! 那我们就欢乐的学习另外一种神奇的线段树吧!(雾 他叫做zkw线段树 这个数据结构灰常好写(虽然线段树本身也特别好写……) 速度快(貌似只在单点更新方面比 ...
- 线段树和zkw线段树
作者作为一个蒟蒻,也是最近才自学了线段树,不对的地方欢迎大佬们评论,但是不要喷谢谢 好啦,我们就开始说说线段树吧 线段树是个支持区间操作和查询的东东,平时的话还是蛮实用的 下面以最基本的区间加以及查询 ...
- ZKW线段树 非递归版本的线段树
学习和参考 下面是支持区间修改和区间查询的zkw线段树模板,先记下来. #include <algorithm> #include <iterator> #include &l ...
- V-Parenthesis 前缀+ZKW线段树或RMQ
Bobo has a balanced parenthesis sequence P=p 1 p 2…p n of length n and q questions. The i-th questio ...
- ZKW线段树
简介 zkw线段树虽然是线段树的另一种写法,但是本质上已经和普通的递归版线段树不一样了,是一种介于树状数组和线段树中间的存在,一些功能上的实现比树状数组多,而且比线段树好写且常数小. 普通线段树采用从 ...
- zkw线段树详解
转载自:http://blog.csdn.net/qq_18455665/article/details/50989113 前言 首先说说出处: 清华大学 张昆玮(zkw) - ppt <统计的 ...
随机推荐
- 我的工具:Db SQL Monitor
SQL Monitor 是一款界面简洁.绿色小巧的sql活动监视器,它能够帮助用户对 SQL Server 运行进程和Job进行实时监视,您可以查看当前执行的SQL/命令并终止. 工具下载地址:htt ...
- SpringMVC 框架介绍以及环境搭建
目录 前端设计模式介绍 分析前端设计模式 Spring MVC简单介绍 Spring和Spring MVC的关系 配置Spring MVC的环境并简单测试 前端设计模式介绍 前端设计模式其实和前端没啥 ...
- jsp假分页
假分页:从数据库中取出所有的数据,然后分页在界面上显示.访问一次数据库,但由于选择的数据量比较大,所以第一次花费时间比较长,但之后每一页的显示都是直接.快速的,避免对数据库的多次访问. 真分页:确定要 ...
- css居中flex
css利用flex实现居中(子元素可以不必管宽高):
- maven 将第三方jar包转成maven的jar包
转载:https://blog.csdn.net/qq_40644583/article/details/81475135 1.首先你需要准备外部jar包 我的这个jar包现在以及下载解压到桌面 地址 ...
- SpringBoot配置mybatis
一直都说SpringBoot是零配置,当然,真正实现零配置是不可能的,但是在配置mybatis这里真的是太简单了,哈哈,下面我们一起看一下. 1.先导入基于SpringBoot的mybatis依赖包 ...
- 从输入URL到页面加载的全过程
前面的话 本文将详细介绍从输入URL到页面加载的全过程 概述 从输入URL到页面加载的主干流程如下: 1.浏览器构建HTTP Request请求 2.网络传输 3.服务器构建HTTP Response ...
- 堆以及一些用法 QWQ这是写得最认真的板子题
最近一直在学图论,然后吧,由于学的东西实在是太多太杂了,加上蒟蒻本蒻又经常颓,所以落了好多好多板子题的整理没写啊嘤嘤嘤,不过把这些东西学的差不多了,再一块写个整理,其实感觉还不错?????也算是很神奇 ...
- 修改linux下yum镜像源为国内镜像
修改为163yum源-mirrors.163.com 1.首先备份系统自带yum源配置文件/etc/yum.repos.d/CentOS-Base.repo [root@localhost ~]# m ...
- BZOJ2287 消失之物
这题貌似是个权限题qwq,我是用离线题库+本地数据包测的 题目大意: 给你\(n\)个体积分别为\(w[i]\)的物品和容积\(m\),问你将每一件物品分别去掉之后,拼出\(1\)~\(m\)中每一个 ...