線段樹(區間修改 加減法)

2021-10-04 19:47:22 字數 3304 閱讀 3845

#include

#include

#define maxsize 1000

using

namespace std;

// 定義樹結點結構

struct nodetree[maxsize]

;// 線段樹需要開闢 4*n + 1 的空間

void

build_tree

(int arr[

],node tree,

int i,

int start,

int end)

int mid =

(start + end)/2

;int left_node =

2* i;

int right_node =

2* i +1;

build_tree

(arr,tree,left_node, start,mid)

;build_tree

(arr,tree,right_node,mid+

1,end)

; tree[i]

.data = tree[left_node]

.data + tree[right_node]

.data;

return;}

/*int search(int arr,node tree,int i,int l,int r)

int mid = (tree[i].l + tree[i].r) / 2;

int left_node = 2 * i;

int right_node = 2 * i + 1;

int s = 0;

if(mid >= l )

if(mid+1 <= r)

return s;

}*/void

add(

int arr[

],node tree,

int i,

int idx,

int val)

int mid =

(tree[i]

.l + tree[i]

.r)/2;

int left_node =

2* i;

int right_node =

2* i +1;

if(idx <= mid)

// 若在左子樹里,則修改左子樹

add(arr,tree,left_node, idx,val)

;else

// 若在右子樹里,則修改右子樹

add(arr,tree,right_node,idx,val)

;// 更新其父結點的值

tree[i]

.data = tree[left_node]

.data + tree[right_node]

.data;

return;}

// 懶惰標記:

// 當乙個區間的值發生 加減變化時,我不把它立刻實現,而是存放在父節點的 lz 域中,要查詢時直接從父節點返回

// 1、如果當前區間被完全覆蓋在目標區間裡,將這個區間的sum + k*(tree[i].r-tree[i].l+1)

// 2、如果沒有完全覆蓋,則先下傳懶標記

// 3、如果這個區間的左兒子和目標區間有交集,那麼搜尋左兒子

// 4、如果這個區間的右兒子和目標區間有交集,那麼搜尋右兒子

void

push_down

(int i)

}void

add(

int arr[

],node tree,

int i,

int l,

int r,

int k)

// 如果不是完全包含,則需要往下做修改,將懶惰標記下傳給兒子節點,再求和

push_down

(i);

int mid =

(tree[i]

.l + tree[i]

.r )/2

;int left_node =

2* i;

int right_node =

2* i +1;

if(l <= mid)

if(r >= mid+1)

//更新該節點的值

tree[i]

.data = tree[left_node]

.data + tree[i]

.data;

return;}

intsearch

(int arr[

],node tree,

int i,

int l,

int r)

// 如果沒有交集,則返回0

if(tree[i]

.r < l || tree[i]

.l > r)

return0;

// 如果不是完全包含,就要 push_down

push_down

(i);

int s =0;

int mid =

(tree[i]

.l + tree[i]

.r )/2

;int left_node =

2* i;

int right_node =

2* i +1;

if(l <= mid)

if(mid+

1<= r)

return s;

}int

main()

;const

int size =

(sizeof

(arr)

/sizeof

(*arr));

build_tree

(arr,tree,1,

1,5)

;for

(int i =

1;i<=

3*size;

++i)

printf

("\n");

add(arr,tree,1,

5,1)

;for

(int i =

1;i<=

3*size;

++i)

printf

("\n");

printf

("sum[%d-%d] = %d\n",1

,5,search

(arr,tree,1,

1,5)

);for(

int i =

1;i<=size;

++i)

return0;

}

線段樹的單點修改加區間修改

const int maxn 1e6 5 int a maxn 存每個數的值 struct node tree maxn 4 void pushup int id 區間合併 void pushdown 區間下放,進行區間修改的時候用到 void build int id,int ll,int rr ...

線段樹 區間修改

我們對於線段樹的區間修改你可以用乙個最傻的辦法迴圈進行單點修改 時間複雜度太高十分麻瓜 所以,我們要用乙個聰明的做法延遲標記 lazy 我們在執行修改指令時,同樣可以在 l pl pr r 的情況下立即返回,只不過在回溯之前向節點p增加乙個標記,標識 該節點曾經被修改過,但其子節點尚未被更新 如果在...

線段樹 區間修改(加法) 乙個簡單的整數問題

你有n個整數,a1,a2,an。你需要處理兩種操作。一種操作是在給定間隔中為每個數字新增一些給定數字。另一種是要求給定間隔中的數字總和。第一行包含兩個數字n和q.1 n,q 100000。第二行包含n個數字,a1,a2,an的初始值。1000000000 ai 1000000000。接下來的q行中的...