Segment Tree(線段樹)
0.適用範圍
線段樹是一種資料結構,用於進行區間快速修改及查詢。
1.先導知識
二叉樹(略)
2.定義
線段樹的每個結點代表著一個區間,我們將這棵樹以陣列的方式儲存。
設一個下標為、代表區間的結點,二分該結點,則該結點的左孩子(假如有的話)下標為、代表區間;右孩子(假如有的話)下標為、代表區間
從線段樹的定義中可以發現,需要開大約4倍空間(或者說是大於等於n的最小的2的正數次冪*2)
3.lazy標誌
lazy標誌表示該下標對於該lazy值已計入計算,但其子節點還未用這個lazy值進行更新
因此需要使用pushDown函式實現lazy標誌的傳遞
void pushDown(int id)
{
if(segTree[id].lazy)
{
int lid=id<<1,rid=id<<1|1;
segTree[lid].lazy+=segTree[id].lazy;
segTree[rid].lazy+=segTree[id].lazy;
segTree[lid].val+=segTree[id].lazy*(segTree[lid].r-segTree[lid].l+1);
segTree[rid].val+=segTree[id].lazy*(segTree[rid].r-segTree[rid].l+1);
segTree[id].lazy=0;
}
}//向下傳遞lazy
4.建樹
按照定義建樹即可
void pushUp(int id)
{
segTree[id].val=segTree[id<<1].val+segTree[id<<1|1].val;
}//上推
void build(int l,int r,int id)
{
segTree[id].l=l;
segTree[id].r=r;
if(l==r)
{
//-------------------------------------------------
segTree[id].val=arr[l];
//該區間是點,賦值為該點上的值
//-------------------------------------------------
return;
}
int m=(l+r)>>1;
build(l,m,id<<1);
build(m+1,r,id<<1|1);
pushUp(id);
}//建樹
5.更新
void apply(int id,ll add)
{
//-------------------------------------------------
//視題目情況做操作
segTree[id].val+=add*(segTree[id].r-segTree[id].l+1);
segTree[id].lazy+=add;
//此處為區間加
//-------------------------------------------------
}//更新時具體需要做的操作
void update(int l,int r,int id,ll add)
{
//-------------------------------------------------
if(r<segTree[id].l||l>segTree[id].r) return;
//該區間與要更新的區間不相交
//-------------------------------------------------
if(l<=segTree[id].l&&r>=segTree[id].r)
{
//-------------------------------------------------
apply(id,add);
return;
//該區間整個包含於要更新的區間
//-------------------------------------------------
}
pushDown(id);
update(l,r,id<<1,add);
update(l,r,id<<1|1,add);
pushUp(id);
}//更新
6.查詢
ll query(int l,int r,int id)
{
if(r<segTree[id].l||l>segTree[id].r) return 0;
if(l<=segTree[id].l&&segTree[id].r<=r)
{
return segTree[id].val;
}
pushDown(id);
ll ans=0;
ans+=query(l,r,id<<1);
ans+=query(l,r,id<<1|1);
return ans;
}//查詢
相關文章
- 線段樹入門(Segment Tree)
- 【學習筆記】Segment Tree Beats/吉司機線段樹筆記
- HDU 3333 Turing Tree(線段樹+離線操作)
- BZOJ3165: [Heoi2013]Segment(李超線段樹)
- segment tree beats
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- [ABC337G] Tree Inversion(換根 dp + 值域線段樹)
- 線段樹
- 線~段~樹
- 01 線段樹
- 線段樹--RMQMQ
- 【模版】線段樹
- 線段樹模板
- 線段樹 hate it
- ut.cpp 最大線段並減線段交 [線段樹]
- 李超線段樹
- 線段樹進階
- 權值線段樹
- 線段樹筆記筆記
- 線段樹入門
- 洛谷題單指南-線段樹-P3373 【模板】線段樹 2
- 懶標記線段樹
- 可持久化線段樹持久化
- 線段樹(超詳解)
- 線段樹 transformation——hdu 4578ORM
- 深入理解線段樹
- 線段樹簡單思路
- 線段樹擴充套件套件
- 第二課——線段樹
- 線段樹模板總結
- 線段樹(毒瘤)總結
- POJ 3667 Hotel 線段樹
- poj 2667 hotel 線段樹
- 線段樹 - 多組圖帶你從頭到尾徹底理解線段樹
- 資料結構之樹( 線段樹,字典樹)資料結構
- hdu 1698 線段樹 一段更新染色
- 線段樹也能是 Trie 樹 題解
- 線段樹學習筆記筆記