今天做到一題是線段樹題,在此補充一下我自己缺失的知識點
首先介紹乙個寫的賊好的部落格
準備每天看一篇,每天增加乙個小的知識點。
今天是線段樹
首先是建樹的過程,因為鄙人畫圖技術有限,所以大家還是參考那個部落格的講解吧,這裡主要是一些**
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 ...