博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ACM知识----线段树
阅读量:3946 次
发布时间:2019-05-24

本文共 1083 字,大约阅读时间需要 3 分钟。

近几天有些自闭,我觉得自己身上有太多的东西没有学会,我决定一点点来,每天争取学一个知识点,今天份记录,线段树。

线段树是一种以二叉树为原型,将树形结构各个节点划分为区间的一种结构,其中全部的区间就是根节点,如一个节点【l,r】,其子节点就是【l,l+r/2】与【(l+r)/2+1,r】,也就是把区间二等分,直到最后的叶子节点全部都是一个单一数据。

如果区间长度为n,那么树的高度最大为log2(n-1)+2.,所以如果要修改某个值,包括这个值的点在每一层区间当中只有一个,所以更改的次数最大值即为log2(n-1)+2次,既整颗树的高度,容易看出时间复杂度仅仅只有log2n。

如果要进行区间查询,一般要从树的叶子节点出发,查询其包含的内容所构成的子区间时,只需要一层层往上找,最终找到所有包含内容的子区间,当然也可以取一些别的零碎的区间,可以用来解决一些查找的区间问题。

建树函数:

void dataup(int rt){Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];}      //用于更新每个父节点的数据

void build(int l,int r,int jd){ 

//l表示左区间,r表示有区间端点,jd表示节点

    if(l==r) {

//抵达叶节点回溯,此处用了递归的思想

        sum[jd]=p[l];   //p是存储的数据元素,sum表示的是线段树存储数组值,当前sum是求整个区间的和,当为不同区间是sum不同

        return;  

    }  

    int m=(l+r)>>1;  

    build(l,m,jd<<1);  

    build(m+1,r,jd<<1|1);  

    dataup(jd);  

}  

而修改一个数据的值相对于简单一点,就是一直遍历到叶子节点,把那个改变的值在本点加上,然后回溯更新父节点的值,利用上面的dataup函数即可,不多做赘述。

而相对于修改一点的值,修改整个区间则要更麻烦一些,我们需要记一下需要修改的值的区间左右端点,然后构成函数,当前所操作的区间如果包含于修改的区间之内那么我们就把这个区间的数据改变,需要右区间端点减左区间端点加一乘要改变的数,如果不完全包含于修改区间也没关系,我们写个判断,看这个区间是否完全与需要操作的区间无交集,如果有那么向下递归,递归的作用就是更新一下前面的节点数据。这样就完成了整个树结构的区间操作的更新。

区间查询也不麻烦,从开始往下找,当找到完全包含于查询区间的数值上,加在答案上就可以了。

这就是线段树基本实现方式,过两天更新两道题,我要找找当初网络赛干掉我的题的题解,争取早日更新。

加油,臭咸鱼!!

转载地址:http://pomwi.baihongyu.com/

你可能感兴趣的文章
上司最恨员工哪十大"罪行"
查看>>
和上司沟通必备8个黄金句
查看>>
竹笋和榕树的管理学
查看>>
让“抱怨”促进公司进步
查看>>
职场“站队”你站对了吗?
查看>>
培养员工能力与责任
查看>>
细分市场制胜
查看>>
空降兵变革是怎样失败的
查看>>
伟大决策的6大基石
查看>>
MTK编译笔记
查看>>
深入理解各种指针
查看>>
Android的SeekBar
查看>>
SMS 和 MMS 在输入字母的响应不一致
查看>>
如何判断手机是否处于漫游状态?
查看>>
恢复出厂设置时删除手机上所有联系人
查看>>
根据Sim卡的插卡情况过滤通话记录
查看>>
联系查看两张卡的未接电话记录
查看>>
把拒接电话作为已经接电话写到call log中
查看>>
FDN号码完全匹配
查看>>
Cosmos 拨号界面保存号码时先提示选择存储位置
查看>>