线段树-持续更新中

线段树用于解决区间的问题,算是对分块算法的优化,但功能更为强大。

我们定义一颗树,树上存储的结构为区间、统计值等。

线段树的存储结构:

1.链表:

struct Node{
    int left,right;
    Node *lchild,*rchild; 
};

2.数组模拟链表法

定义4个int数组,left[],right[],lchid[],rchild[]来分别存储左端点,右端点,左孩子索引,右孩子索引。

3.数组形成的堆结构

对于一个索引i对应的区间为[l,r],如果区间不是叶子区间,则分出左孩子和右孩子,mid=(l+r)/2,左孩子索引为2*i,对应区间为[l,mid],右孩子索引为2*i+1,对应区间为[mid+1,r]。

4.更为紧凑的结构

这里要分析一下堆结构的存储损耗。我们直接考虑满二叉树的情形,节点个数为2^{h}-1

假设初始的区间为[1,n]。h=\left \lceil log_{n} \right \rceil+1,加1是因为本身初始区间占据一层,于是保险起见,节点个数算得的结果为4n-1。

然而4n-1的区间长度是假象,只是因为在最后一层多了仅仅几个节点而导致索引范围的扩大,因此实际上真正存有区间的还是2n-1。

一种改进的方式是对于区间为[l,r)的节点,存储在(l+r-1) bitwise_or diff(1,r-1)的索引种,diff为判断传入的两值是否相等的函数,相等返回0,不等返回1。bitwise_or为按位或运算。

注意:前三种存储都可以存区间[l,r],但是第四种要求只能是[l,r)。

猜你喜欢

转载自blog.csdn.net/qq_39304630/article/details/85212440