線段樹2(區間更新)

2021-08-06 02:52:47 字數 2710 閱讀 6069

區間更新是指更新某個區間內的葉子節點的值,因為涉及到的葉子節點不止乙個,而葉子節點會影響其相應的非葉父節點,那麼回溯需要更新的非葉子節點也會有很多,如果一次性更新完,操作的時間複雜度肯定不是o(lgn),例如當我們要更新區間[0,3]內的葉子節點時,需要更新出了葉子節點3,9外的所有其他節點。為此引入了線段樹中的延遲標記概念,這也是線段樹的精華所在。

延遲標記:每個節點新增加乙個標記,記錄這個節點是否進行了某種修改(這種修改操作會影響其子節點),對於任意區間的修改,我們先按照區間查詢的方式將其劃分成線段樹中的節點,然後修改這些節點的資訊,並給這些節點標記上代表這種修改操作的標記。在修改和查詢的時候,如果我們到了乙個節點p,並且決定考慮其子節點,那麼我們就要看節點p是否被標記,如果有,就要按照標記修改其子節點的資訊,並且給子節點都標上相同的標記,同時消掉節點p的標記。

const int infinite = int_max;

const int maxnum = 1000;

struct segtreenode

segtree[maxnum];//定義線段樹

/*功能:構建線段樹

root:當前線段樹的根節點下標

arr: 用來構造線段樹的陣列

istart:陣列的起始位置

iend:陣列的結束位置

*/void build(int root, int arr, int istart, int iend)}/*

功能:當前節點的標誌域向孩子節點傳遞

root: 當前線段樹的根節點下標

*/void pushdown(int root)}/*

功能:線段樹的區間查詢

root:當前線段樹的根節點下標

[nstart, nend]: 當前節點所表示的區間

[qstart, qend]: 此次查詢的區間

*/int query(int root, int nstart, int nend, int qstart, int qend)

/*功能:更新線段樹中某個區間內葉子節點的值

root:當前線段樹的根節點下標

[nstart, nend]: 當前節點所表示的區間

[ustart, uend]: 待更新的區間

addval: 更新的值(原來的值加上addval)

*/void update(int root, int nstart, int nend, int ustart, int uend, int addval)

pushdown(root); //延遲標記向下傳遞

//更新左右孩子節點

int mid = (nstart + nend) / 2;

update(root*2+1, nstart, mid, ustart, uend, addval);

update(root*2+2, mid+1, nend, ustart, uend, addval);

//根據左右子樹的值回溯更新當前節點的值

segtree[root].val = min(segtree[root*2+1].val, segtree[root*2+2].val);

}

下面上個例題。類似的

poj - 3468

#include #include #include#include #include #include #include #include#include#include#includeusing namespace std;

const int maxn=1000000+5;

const int inf=0x3f3f3f3f;

int n,m;

struct node

};node tree[maxn*2];

long long arr[maxn];

int t;

void build(int root,int istart,int iend)

void update(int root,int istart,int iend,int l,int r,int a)

else

}int main()

}return 0;

}

hdu - 1698

#include #include #include#include #include #include #include #include#include#include#includeusing namespace std;

const int maxn=200000+5;

const int inf=0x3f3f3f3f;

int n,m;

struct node

;node tree[maxn*2];

int t;

void build(int root,int istart,int iend)

}void pushdown(int root,int l,int r)

}void update(int root,int istart,int iend,int l,int r,int a)

else

}int main()

printf("case %d: the total value of the hook is %d.\n",ka,tree[1].val);

}return 0;

}

線段樹(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...

模板 線段樹(2)區間修改

好像叫做懶操作來著。還是叫延遲修改更高大上一點吧 區間修改 兩種操作 add l r v 把a l a l 1 a r 的值全部增加v query l r 計算子串行a l a l 1 a r 的元素和,最小值和最大值 修改 查詢的範圍均為 y1,y2 維護節點o,它對應區間 l,r void ma...

hdu1968 區間更新 區間求和(線段樹)

這次是把某個區間全部更新為乙個值,而不是增加或減少。最後詢問一下區間總和。思路還是差不多的。在更新時,當我們將乙個節點所維護的區間更新後,可以用這個區間的長度 新的值,即 tree x sum tree x r tree x l 1 tree x data。在查詢或更新區間時,可以將tree x d...