zkw线段树学习笔记

  1. zkw线段树是什么
    zkw线段树,顾名思义,是一种线段树。
    他是线段树的非递归形式,虽然没递归版线段树那么通用,但它的常数与码量吊打递归版线段树。

  2. zkw线段树的构造
    说了那么多,不会写也没用啊。
    递归式线段树自上往下遍历,即从根节点到叶节点,再回到根节点。
    zkw则正好相反,直接从叶节点到根节点。
    这就要我们记录下每一个叶节点的位置。
    但在一般情况下不太好记录。
    image
    如图,每个叶节点的位置不太规律。
    但有一种特殊情况。
    image
    也就是叶节点的个数是2的次幂的时候,线段树是一棵满二叉树。
    zkw线段树的方法就是在原数列后面补0,使其变为满二叉树的形态。
    这样叶子节点就很好找。
    构建代码如下:

    int M,tr[N<<2],n;//n为原始数据个数,tr为线段树,M为填充后数据个数
    void build(){
    	for(M=1;M<=n;M<<=1);
    	//根据需要自行补充
    }
    
  3. zkw线段树单点操作
    可以发现,M既是填充后数据个数,也是填充后第一个数据的编号,将其留空(有用)
    因此,原数据第i个对应的叶节点编号为i+M
    单点修改就在叶节点直接修改,向上pushup

    //单点增加代码
    void modify(int pos,int x){
    	pos+=M;tr[pos]+=x;pos>>=1;
    	while(pos){
    		tr[pos]=tr[pos<<1]+tr[pos<<1|1];
    	}
    }
    

    单点查询更加简单。相信不用说了。

  4. zkw线段树区间操作
    区间查询就当然不能一个一个查了这和暴力有什么区别
    正解:设两个指针s,t,初始时分别指向l1,r+1的位置(0的位置派上用场了)。
    然后同步向上跳,父亲节点相同(即成为兄弟时)时停止向上跳。
    如果s为父亲的左儿子,那将s兄弟的数据合并。
    因为s肯定包含l1,且t不为s兄弟,所以s兄弟数据在l,r范围内。
    同理,如果t为父亲的右儿子,那将t兄弟的数据合并。

posted @   Andy__Lin  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示