線段樹 動態區間查詢

2021-08-13 11:25:29 字數 1546 閱讀 6512

現在手上有乙個陣列a[n],讓我們來求乙個區間的和

這簡直太簡單了!

我們寫乙個字首和就可以在o(1)解決問題了!

問題公升級:

有兩種操作,乙個是修改其中某個變數的值,

另乙個是求區間和

這。。我只能o(n²)去做了==

別怕, 線段樹可以解決你的問題。

既然是線段樹,那麼一定具有乙個樹的結構。

這個樹和其他樹不一樣,線段樹是用來維護我們手中的陣列的

樹的結點有這麼幾個屬性:l,r,w

l代表left,是這個結點對應區間的左端點

r代表right,是這個結點對應區間的右端點

w代表這個區間內的區間和

struct nodetree[maxn];
那我們來想一下大致的過程吧:

首先我們要對於初始的陣列a[n]來把這個線段樹建立起來

然後,如果要修改乙個值,我們就要修改對應葉子結點和它所有的父節點

查詢區間和emmm

把乙個大區間分成許多我們維護的小區間就好了~

看上去挺簡單的

建樹也好,建堆也好,這種操作我們經常使用,就是初始化嘛~

我們從根節點開始初始化,把區間逐漸二分下去。

void build_tree(int x,int left,int right)

build_tree(2*x,left,(left+right)/2);

build_tree(2*x+1,(left+right)/2+1,right);

//左右分別遞迴呼叫

return ;

}int main()

這樣我們就能遞迴的建立乙個線段樹了。

剛剛的**裡出現了什麼奇怪的東西!

是的,我們呼叫了還沒寫的change函式

change,就是把乙個節點的值進行修改(現在我們簡單的定義為加法)

獲取的引數是結點的序號,還有改動的值

然後遞迴向上修改所有的父親節點:

void change(int x,int a)
那麼,我們拿到的指令是,修改a[i]

怎麼通過a[i]找到對應的那個葉子結點呢?

二分嘛:

int find(int x,int p,int left,int right)
我們已經可以修改並且維護這顆大樹了!

接下來只要算算區間和究竟是多少就好了

我們拿到乙個區間,這個區間很大可能沒有直接與之對應的節點

往往可能是5個,6個節點拼湊出要求的區間

寫幾個判斷語句,然後遞迴:

int add(int x,int left,int right)
呼叫的時候,x為1,因為要從根節點開始尋找

最後祝各位oier武運昌隆!!!

線段樹 區間更新 區間查詢

題意 題解 如果採用單點更新的思路對區間進行更新的話時間複雜度會比較高,因此用了乙個lazy陣列 俗稱懶人標記 它為什麼叫懶人標記呢,比如更新的區間為 l,r z,而l到r覆蓋了線段樹某乙個節點的區間,那麼可以將該節點對應的lazy陣列的值加上z,同時更新該節點的值,這樣就可以避免更新它子孫節點的值...

線段樹(點查詢 區間查詢 區間修改)模板

簡單記錄一下自己的 以後方便複習 其實有了這樣子的乙個模板,題目變式自己改改就可以,比如說加減變成乘除等等。pragma gcc optimize 3,ofast inline include include include include include include include inclu...

線段樹動態開點區間加區間求和

陝西師範大學第七屆程式設計競賽網路同步賽 h.萬惡的柯怡 保證葉子節點被完整的覆蓋,需要開節點,就把左右兒子都開出來,其餘和普通線段樹一樣。用結構體內部函式,記憶體不足,第一次遇見本地問題不嚴重 不明嚼慄?include typedef long long ll const int n 400001...