線段樹 (區間和 單點操作)

2021-10-11 12:45:29 字數 3434 閱讀 9910

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define fast ios::sync_with_stdio(false)

#define ll long long

#pragma gcc optimize(2)

using

namespace std;

const

int n =

2e5+10;

int tree[n]

;void

build_tree

(int arr,

int tree,

int node,

int start,

int end)

// 建立樹的操作 (node是當前tree陣列中的下標,start和end是node節點存放的arr陣列中的該範圍的左右界)

int mid =

(start + end)/2

;// 劈分陣列 (取當前arr範圍的一半向下取整)

build_tree

(arr,tree,

2* node +

1,start,mid)

;build_tree

(arr,tree,

2* node +

2,mid +

1,end)

;// 到這裡tree中node節點的左右子樹都已經建立好了,node節點的值就等於其左右子樹的節點之和

tree[node]

= tree[

2* node +1]

+ tree[

2* node +2]

;}void

update_node

(int arr,

int tree,

int node,

int start,

int end,

int idx,

int val)

// 修改線段樹中某個節點的操作 (o(log(n)))

int mid =

(start + end)/2

;if(idx >= start && idx <= mid)

else

tree[node]

= tree[

2* node +1]

+ tree[

2* node +2]

;// 當前樹階段的左右子樹都已經修改好了,重新計算當前根節點的值

}int

seek_tree

(int arr,

int tree,

int node,

int start,

int end,

int l,

int r)

// 求區間和的操作

intmain

(void);

int size =6;

int tree[n]=;

build_tree

(arr,tree,0,

0,size -1)

;//檢查樹的建立情況

for(

int i =

0; i <

15; i++

) cout << tree[i]

<<

" ";

cout << endl;

update_node

(arr,tree,0,

0,size -1,

4,6)

;for

(int i =

0; i <

15; i++

) cout << tree[i]

<<

" ";

cout << endl;

// 輸出通過線段樹計算得來的arr陣列中下標2到下標5範圍的元素和

cout <<

seek_tree

(arr,tree,0,

0,size -1,

2,5)

<< endl;

return0;

}

改為求區間的最大值

void

build_tree

(int arr,

int tree,

int node,

int start,

int end)

int mid =

(start + end)/2

;build_tree

(arr,tree,

2* node +

1,start,mid)

;build_tree

(arr,tree,

2* node +

2,mid +

1,end);

tree[node]

=max

(tree[

2* node +1]

, tree[

2* node +2]

);}void

update_node

(int arr,

int tree,

int node,

int start,

int end,

int idx,

int val)

int mid =

(start + end)/2

;if(idx >= start && idx <= mid)

else

tree[node]

=max

(tree[

2* node +1]

, tree[

2* node +2]

);}int

seek_tree

(int arr,

int tree,

int node,

int start,

int end,

int l,

int r)

// 求區間和的操作

else

if(start >= l && end <= r)

int mid =

(start + end)/2

;int left_max =

seek_tree

(arr,tree,node *2+

1,start,mid,l,r)

;int right_max =

seek_tree

(arr,tree,node *2+

2,mid +

1,end,l,r)

;return

max(left_max , right_max)

;}

線段樹 離散區間,單點維護區間

這道題當時用線段樹搞不行,用主席樹搞,也不行。當場自閉。其實當時想到離散,但是沒想到用單點維護線段樹的區間。你這樣想,無非就是2e6次詢問,最多1 e9被分成最多2e6區間,我們要求的位置,一定在這2e6點的右邊第乙個。那麼把這個點,以及這個點x以及x 1的點儲存下來。維護的時候,線段樹初始化所有的...

線段樹 離散區間,單點維護區間

這道題當時用線段樹搞不行,用主席樹搞,也不行。當場自閉。其實當時想到離散,但是沒想到用單點維護線段樹的區間。你這樣想,無非就是2e6次詢問,最多1 e9被分成最多2e6區間,我們要求的位置,一定在這2e6點的右邊第乙個。那麼把這個點,以及這個點x以及x 1的點儲存下來。維護的時候,線段樹初始化所有的...

線段樹(單點操作)

單點操作 元素 struct node tr maxn 2 節點型別 建樹 void pushup int m void build int m,int l,int r 直接結束 int mid l r 1 求中間值 build m 1,l,mid 左半邊 m 2 build m 1 1,mid 1...