線段樹初級

2021-10-08 09:54:16 字數 3896 閱讀 6537

今天做到一題是線段樹題,在此補充一下我自己缺失的知識點

首先介紹乙個寫的賊好的部落格

準備每天看一篇,每天增加乙個小的知識點。

今天是線段樹

首先是建樹的過程,因為鄙人畫圖技術有限,所以大家還是參考那個部落格的講解吧,這裡主要是一些**

void

buildtree

(int l,

int r,

int n)

int m=

(l+r)/2

;buildtree

(l,m,n<<1)

;buildtree

(m+1

,r,n<<1|

1); tree[n]

=tree[n*2]

+tree[n<<2|

1];}

建好樹之後,會出現乙個問題就是tree的陣列開多大,答案是4*n,上述鏈結中有提到過這個問題。

下面我們就要實現

區間查詢,可以查詢到某一段區間內的最值問題,還有區間和問題。

首先是查詢值的問題

int

search

(int i,

int l,

int r)

if(tree[i]

.l.r>r)

if(tree[i*1]

.r>=l)

s+=search

(i<<

1,l,r);if

(tree[i<<1|

1].l<=r)

s+=search

(i<<1|

1,l,r)

;return s;

}

這是查詢區間和的問題,時間複雜度大概是o(logn)

單點修改

void

change

(int i,

int dis)

if(dis.r)change

(i<<

1,dis);if

(dis>=tree[i<<|1

].l)

change

(i<<1|

1,dis)

; tree[i]

.sum=tree[i<<1]

.sum+tree[i<<1|

1].sum;

}

注意單點修改時一定要更新樹上的所有資訊

區間修改

void

search

(int i,

int l,

int r,

int k)

if(tree[i<<1]

.r>=l)

search

(i<<

1,l,r,k);if

(tree[i<<1|

1].l<=r)

search

(i<<1|

1,l,r,k)

;}

這段**給的不太行,

然後 我就去做題了,做了

傳送門:

我發現光有這些理論那是不可以的

還得實踐,實踐出真知啊

#include

using namespace std;

int maxn=2*

1e6;

int a1,b,c;

int a[

500010];

int s=0;

int ans=0;

typedef

struct node

node;

node tree[

2000010];

void

build

(int left,

int right,

int index)

intadd

(int index)

tree[index]

.value=

add(index*2)

+add

(index*2+

1);return tree[index]

.value;

}void

change

(int i,

int k,

int dis)

if(dis>=tree[i<<1|

1].l)change

(i<<1|

1,k,dis);if

(dis<=tree[i<<1]

.r)change

(i<<

1,k,dis)

; tree[i]

.value=tree[i<<1]

.value+tree[i<<1|

1].value;

}void

search

(int i,

int l,

int r)

if(tree[i*2]

.r>=l)

search

(i*2

,l,r);if

(tree[i*2+

1].l<=r)

search

(i*2+1

,l,r);}

intmain()

// cout<<" 是我的問題嗎",n,1);

add(1)

;// cout<<"哦買噶"(int i=

0;i}

ac**,

這道題我調了一天,首先是tree陣列的大小一定要開好,其次就是,建樹,應如上面**那樣寫,要不然,就會tle,時間複雜度會增加。

線段樹模板2

這個區間修改和單值查詢,有乙個技巧,就是對於樹可以不直接呼叫add函式,因為其輸出時,就只有乙個數字,因此方便計算,可以省去乙個add函式。

#include

using namespace std;

typedef

struct node

node;

node tree[

2000010];

int a[

500010];

int a1,b,c;

int ans=0;

void

buildtree

(int l,

int r,

int i)

int mid=

(l+r)/2

;buildtree

(l,mid,i<<1)

;buildtree

(mid+

1,r,i<<1|

1);}

void

change

(int l,

int r,

int i,

int k)

if(tree[i<<1]

.r>=l)

change

(l,r,i<<

1,k);if

(tree[i<<1|

1].l<=r)

change

(l,r,i<<1|

1,k);}

void

search

(int dis,

int i)

if(dis>=tree[i<<1|

1].l)search

(dis,i<<1|

1);if

(dis<=tree[i<<1]

.r)search

(dis,i<<1)

;}intmain()

buildtree(1

,n,1);

for(

int i=

0;i(a1==2)

}}

因為忘記建樹,wa了好久,awsl

hdu 1556 初級線段樹

include include include define max 100005 define mid l r 1 define lson l,m,rt 1 define rson m 1,r,rt 1 1 using namespace std int n struct tree tree tr...

線段樹學習 初級基礎操作

這篇部落格是不完整的,現在的知識儲備,貌似只能寫一些基礎的應用的 首先的話,來談下自己對線段樹的認識 線段樹可以解決區間加法的問題,比如說,最大值,最小值,區間和的問題,但是不可以解決不符合區間加法的問題,比如說眾數問題。在網上看了很多版本的線段樹,看到了很多的結構體型別的線段樹。個人感覺結構體型別...

敵兵布陣 HDU 1166 (初級線段樹)

think 1線段樹初級操作 單點更新 區間求和 vjudge題目鏈結 以下為time limit exceeded 區間求和操作不理解,導致直接確定到點,時間複雜度太大 include include using namespace std const int n 2e5 4 int sum n ...