線段樹入門(1)

2021-06-22 17:51:43 字數 1568 閱讀 9007

題目描述 description 一行n個方格,開始每個格仔裡都有乙個整數。現在動態地提出一些問題和修改:提問的形式是求某乙個特定的子區間[a,b]中所有元素的和;修改的規則是指定某乙個格仔x,加上或者減去乙個特定的值a。現在要求你能對每個提問作出正確的回答。1≤n<100000,,提問和修改的總數m<10000條。

輸入描述 input description 輸入檔案第一行為乙個整數n,接下來是n行n個整數,表示格仔中原來的整數。接下乙個正整數m,再接下來有m行,表示m個詢問,第乙個整數表示詢問代號,詢問代號1表示增加,後面的兩個數x和a表示給位置x上的數值增加a,詢問代號2表示區間求和,後面兩個整數表示a和b,表示要求[a,b]之間的區間和。

輸出描述 output description 共m行,每個整數

樣例輸入 sample input 6

4 5 

6 2 1 3

41 3 5

2 1 4

1 1 9

2 2 6

樣例輸出 sample output 22

22資料範圍及提示 data size & hint 1≤n<100000, m<10000 。

[cpp]view plain

copy

print?

# include 

# define n 500000       

// 利用二叉樹的父子節點關係來儲存,因此必須保證陣列開的足夠大

struct

node;  

node st[n];  

inta[n];  

void

build(

intv,

intl,

intr)  

intmid = (l+r)/2;          

// 不是葉子,往下擴充套件

build(2*v,l,mid);  

build(2*v+1,mid+1,r);  

st[v].v=st[v*2].v+st[v*2+1].v;  // 擴充套件出孩子後才能計算value域

}  void

insert(

intv,

intw,

intp)  

if(st[v].l==st[v].r) 

return

;       

// 找到終點,跳出

intmid = (st[v].l+st[v].r)/2;    

if(w<=mid) else

}  intgetsum(

intv,

intl,

intr)  

intmid = (st[v].l+st[v].r)/2;  

if(r<=mid) else

if(l>mid) else

}  intmain(

void

)  build(1,1,n);  

intm,t,a,b;  

for(scanf(

"%d"

,&m);m;m--)else

}  return

0;  

}  

線段樹入門

線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。上圖是一棵典型的線段樹,它對區間 1,10 進行分割,直到單個點。這棵樹的特點 是 1.每一層都是區間 a,b 的乙個劃分,記 l b a 2.一共有log2l層 3.給定乙...

線段樹入門

學習下 線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為...

線段樹 入門

首先線段樹形象來說就是將陣列看成乙個線段,然後不斷的進行分割,儲存在樹中的不同節點上,有點類似於b 樹的定義吧 觀察上圖,首先將整個陣列的某種資訊 最大值或者最小值等 儲存在根節點,對應 1,8 然後對 1,8 線段進行平分,得到 1,4 和 5,8 兩個線段,掛在樹的第二層。這樣節點2儲存了陣列中...