動態求連續區間和 樹狀陣列與線段樹

2021-10-02 18:55:44 字數 2247 閱讀 5586

樹狀陣列,這玩意吧,我也整不明白具體的原理,說的好聽點就是注重實踐,說不好聽點就是揹著這幾個函式會寫就行了

給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 [a,b] 的連續和。

輸入格式

第一行包含兩個整數 n 和 m,分別表示數的個數和操作次數。

第二行包含 n 個整數,表示完整數列。

接下來 m 行,每行包含三個整數 k,a,b (k=0,表示求子數列[a,b]的和;k=1,表示第 a 個數加 b)。

數列從 1 開始計數。

輸出格式

輸出若干行數字,表示 k=0 時,對應的子數列 [a,b] 的連續和。

資料範圍

1≤n≤100000,

1≤m≤100000,

1≤a≤b≤n

輸入樣例:

10 5

1 2 3 4 5 6 7 8 9 10

1 1 5

0 1 3

0 4 8

1 7 5

0 4 8

輸出樣例:

11

3035

樹狀陣列就是求字首和並且能動態的去修改的 o(log n),就是可以在乙個位置上加乙個數(只能是加乙個數)

不多說了,直接放**了,我也解釋不出來啥原理,就記住這個函式跟功能吧:

#include

#include

#include

#include

using

namespace std;

const

int n =

100010

;int n, m;

int a[n]

, tr[n]

;int

lowbit

(int x)

void

add(

int x,

int y)

intquary

(int x)

intmain()

}

線段樹吧,這個玩意倒是好理解,就是把乙個陣列給他不斷地從中間劈開,拆成了乙個二叉樹的樣子,每個位置都是乙個結構體,結構體放著左右區間的乙個範圍,還有乙個要求的東西(區間的和,最大值…)每次進行遞迴查詢

**如下,相應的函式實現的功能都在後面備註了

#include

#include

#include

#include

using

namespace std;

const

int n =

100010

;int w[n]

;struct node

tr[n *4]

;void

pushup

(int u)

//根據左右子節點求出來當前節點

void

build

(int u,

int l,

int r)

//當前是哪乙個結點(u),左右邊界是多少(下標)

;else

;int mid = l + r >>1;

build

(u <<

1, l, mid)

,build

(u <<1|

1, mid +

1, r)

;pushup

(u);}}

intquery

(int u,

int l,

int r)

//看當前這個結點是否被這個範圍全部包含住,沒有就進行遞迴,直到他被包含住了

void

modify

(int u,

int x,

int v)

//從第u個節點,改變他的第x個位置,給他加上v

}int

main()

return0;

}

C 動態求連續區間和(樹狀陣列)

給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 a,b 的連續和。輸入格式 第一行包含兩個整數 n和 m,分別表示數的個數和操作次數。第二行包含 n個整數,表示完整數列。接下來 m行,每行包含三個整數 k,a,b k 0,表示求子數列 a,b 和 k 1,表示第 a 個...

動態求連續區間和 線段樹 模板

給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 a,b 的連續和。輸入格式 第一行包含兩個整數 n和 m,分別表示數的個數和操作次數。第二行包含 n個整數,表示完整數列。接下來 m行,每行包含三個整數 k,a,b k 0,表示求子數列 a,b 的和 k 1,表示第 a ...

C 動態求連續區間和(線段樹)

給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 a,b 的連續和。輸入格式 第一行包含兩個整數 n和 m,分別表示數的個數和操作次數。第二行包含 n個整數,表示完整數列。接下來 m行,每行包含三個整數 k,a,b k 0,表示求子數列 a,b 和 k 1,表示第 a 個...