更快速的、區間的更改、查詢一些東西
eg. 實現一種資料結構使得以下三種計算的時間複雜度為o(logn )
void add(arr, l, r, v);
:將arr陣列中的第l到r的數都增加v
void update(arr, l, r, v);
:將arr陣列中的第l到r的數都修改v
int getsum(arr, l, r);
:將arr陣列中的第l到r的數相加
需要多少空間:
::為什麼從下標1開始:::這樣i節點對應的兩個子節點的座標分別為 2 * i 和 2 * i + 1,可以用位運算表示為 i << 1 和 i << 1 | 1,位運算快
public
class
segmenttree
sum =
newint
[maxn <<2]
; lazy =
newint
[maxn <<2]
; change =
newint
[maxn <<2]
; update =
newboolean
[maxn <<2]
;}private
void
pushup
(int rt)
/** * 下推
* * @param rt 當前的目標節點
* @param ln 目標節點左子樹的節點個數
* @param rn 目標節點柚子樹節點個數
*/private
void
pushdown
(int rt,
int ln,
int rn)
// 下發上次更新後執行的add操作
if(lazy[rt]!=0
)}public
void
build
(int l,
int r,
int rt)
int mid =
(l + r)
>>1;
build
(l, mid, rt <<1)
;build
(mid +
1, r, rt <<1|
1);pushup
(rt);}
public
void
update
(int l,
int r,
int c,
int l,
int r,
int rt)
// 需要下發
int mid =
(l + r)
>>1;
pushdown
(rt, mid - l +
1, r - mid);if
(l <= mid)
if(r > mid)
}/**
* 懶新增
* * @param l 任務左
* @param r 任務右
* @param c 加的數值
* @param l 收到任務的陣列左
* @param r 收到任務的陣列右
* @param rt 根節點
*/public
void
add(
int l,
int r,
int c,
int l,
int r,
int rt)
// 下發任務
int mid =
(l + r)
>>1;
// 下發之前的lazy add任務
pushdown
(rt, mid - l +
1, r - mid);if
(l <= mid)
if(r > mid)
pushup
(rt);}
public
long
query
(int l,
int r,
int l,
int r,
int rt)
int mid =
(l + r)
>>1;
pushdown
(rt, mid - l +
1, r - mid)
;long ans =0;
if(l <= mid)
if(r > mid)
return ans;
}}
左神演算法講堂筆記 05 樹
非遞迴遍歷有點難,目前只能讀懂 裡面的精髓還未真正參透。先序遍歷 不斷地把根入棧,再取出來輸出 根左右,那麼先入棧的肯定是根,要保證輸出左子樹,再輸出右子樹,那麼就要先入棧右子樹。void preorderunrecur node head if node.left null 中序遍歷 必須左子樹走...
左神演算法筆記(九) 字首樹擴充
給定乙個陣列,求子陣列的最大異或和。乙個陣列的異或和為陣列中所有的數異或起來的結果。之前做個乙個找到異或和為0的最長子陣列,思路是將每乙個節點當做異或和的最後乙個節點,求解最長的子陣列。同樣這個題目可以以這種方法解決。以i位置結尾的最大異或和的值,最大的異或和一定包含在其中。暴力解法就是從0 i,1...
線段樹(2)區間修改
快速序列操作i,給出乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構支援一下兩種操作 set l,r,v 把al,al 1,ar的值全部修改為v v 0 query l,r 計算子串行al,al 1,ar的元素和 最小值和最大值。include include using namesp...