18.12.30 【sssx】线段树

每个非叶结点所表示的结点$[a,b]$,左儿子表示区间$[a,frac{a+b}{2}]$,右儿子表示的区间为$[frac{a+b}{2}+1,b]$

叶子结点表示区间长度为1

数据结构

struct CNode
{
    int L,R; //区间起点和终点
    XXXX ; //与区间[L,R]相关的数据
    CNode * pLeft, * pRight; //左右孩子指针(可用idx替代)
};

用一维数组存放线段树(idx)时,数组开到4n大可以确保不越界。

操作

区间分解

  • 从根节点开始递归进行区间分解
  • 走到结点$[L,R]$时,如果该结点就是要找的区间,则找到终止结点,

如果不是,则:取$mid=frac{L+R}{2}$

看要分解的区间与$[L,mid]$或$[mid+1,R]$哪个有交集,就进入哪个区间进行进一步分解,有可能两个区间都进入。

  • 复杂度$O(log(n))$

构建

  • 递归建树,对根节点v建树,v为$[L,R]$
  • 对每个结点,如果L!=R,建立左孩子$[L,frac{L+R}{2}]$,右孩子$[frac{L+R}{2}+1,R]$
  • 复杂度:$O(n)$,n为根节点对应的区间长度

解题技巧

  • 读时更新(参见POJ 3468
    • 更新时,加的区间正好覆盖一个结点,增加其节点的inc值,不再往下走,否则更新sum, 继续往下。
    • 查询时,待查区间不是正好覆盖一个结点就将结点的inc往下带到下一层(累加),并且每次将结点更新到真正的sum,再往下查询
  • 离散化
注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
原文地址:https://www.cnblogs.com/yalphait/p/10199523.html