1. 程式人生 > >18.12.30 【sssx】線段樹

18.12.30 【sssx】線段樹

size 指針 結點 越界 表示 font 復雜 否則 color

每個非葉結點所表示的結點$[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,再往下查詢
  • 離散化

18.12.30 【sssx】線段樹