杭電1166 線段樹(單點更新)

2021-08-20 14:59:35 字數 3258 閱讀 6951

線段樹只是acm眾多演算法中的很普遍的一種,但是他的效率非常高,一般演算法複雜度為o(n)的題,通過線段樹之後,就會變成o(log2(n)),本文是以杭電acm1166題舉例,來對線段樹進行一些了解:杭電1166原題鏈結

比如說求5到12的總人數,用線段樹的話,你只要找到【5,7】、【8,10】、【11,12】這三個部分,加起來就是所求的值。比5+6+7+···+11+12效率多了。

線段樹有三個函式,建樹、更新、查詢。

在開始之前需要定義乙個結構體,用來儲存線段樹節點的各種值

struct sts[

50000*4

];//這裡需要上限×4,防止溢位,

建樹的時候,需要用乙個陣列來儲存資料,用來以後訪問各個節點的資料。

訪問線段樹的方法:例如當前訪問的節點是【1,4】這個節點,用s[4]表示,那麼訪問左孩子節點的時候可以用s[2×4],即s[8];訪問右孩子節點的時候可以用s[2×4+1],即s[9]。

//建樹

/*傳入的引數:

l:左界限

r:右界限

k:剛開始的下標值

*/void

bulid

(int l,

int r,

int k)

int mid =

(l + r)/2

;bulid

(l, mid,

2* k)

;//建立k的左枝

bulid

(mid +

1, r,

2* k +1)

;//建立k的右枝

}

更新

/*

傳入的引數:

d:需要修改的值

n:增加的值(如果是減少,傳參的時候傳入負值就可以)

k:剛開始的下標值

*/void

insert

(int d,

int n,

int k)

int mid =

(s[k]

.l + s[k]

.r)/2;

//取中間點

if(d <= mid)

else

s[k]

.n = s[

2* k]

.n + s[

2* k +1]

.n;//每次使用更新函式的時候都需要更新每個節點上n的值

}

查詢

int ans;

//這裡需要乙個全域性變數,用來儲存答案。

/*傳入的引數:

l:查詢的左界

r:查詢的右界

k:剛開始的下標值

*/void

fin(

int l,

int r,

int k)

int mid;

mid =

(s[k]

.l + s[k]

.r)/2;

if(r <= mid)

else

if(l>mid)

else

}

# include

# include

# include

# include

using namespace std;

struct sts[

50000*4

];/*傳入的引數:

l:左界限

r:右界限

k:剛開始的下標值

*/void

bulid

(int l,

int r,

int k)

int mid =

(l + r)/2

;bulid

(l, mid,

2* k)

;//建立k的左枝

bulid

(mid +

1, r,

2* k +1)

;//建立k的右枝}/*

傳入的引數:

d:需要修改的值

n:增加的值(如果是減少,傳參的時候傳入負值就可以)

k:剛開始的下標值

*/void

insert

(int d,

int n,

int k)

int mid =

(s[k]

.l + s[k]

.r)/2;

//取中間點

if(d <= mid)

else

s[k]

.n = s[

2* k]

.n + s[

2* k +1]

.n;//每次使用更新函式的時候都需要更新每個節點上n的值

}int ans;

//這裡需要乙個全域性變數,用來儲存答案。

/*傳入的引數:

l:查詢的左界

r:查詢的右界

k:剛開始的下標值

*/void

fin(

int l,

int r,

int k)

int mid;

mid =

(s[k]

.l + s[k]

.r)/2;

if(r <= mid)

else

if(l>mid)

else

}int

main()

while(1

)scanf

("%d%d"

,&a,

&b);

if(str[0]

=='a'

)else

if(str[0]

=='s'

)else

if(str[0]

=='q')}

}return0;

}

寫在最後:輸入輸出的時候,一定要用scanf和printf,如果用cin和cout的時候,會超時的,我就是在這裡卡了很久:用cin的時候超時了(超過1000ms),用scanf只有300ms左右。以前根本沒想過cin會比scanf慢那麼多(輸入string字串的時候用的是cin,因為string會方便很多,也可以用char的字元陣列)。

線段樹單點更新hdu1166

學習自 先序建子樹,然後回溯建立父節點 更新時先遞迴更新子節點,然後再回溯更新父節點 回溯思想很重要 include using namespace std const int maxn 50005 int sum maxn 2 void build int l,int r,int rt void ...

HDU 1166 線段樹單點更新

c國的死對頭a國這段時間正在進行軍事演習,所以c國間諜頭子derek和他手下tidy又開始忙乎了。a國在海岸線沿直線布置了n個工兵營地,derek和tidy的任務就是要監視這些工兵營地的活動情況。由於採取了某種先進的監測手段,所以每個工兵營地的人數c國都掌握的一清二楚,每個工兵營地的人數都有可能發生...

杭電 1166 敵兵布陣 (線段樹)

c國的死對頭a國這段時間正在進行軍事演習,所以c國間諜頭子derek和他手下tidy又開始忙乎了。a國在海岸線沿直線布置了n個工兵營地,derek和tidy的任務就是要監視這些工兵營地的活動情況。由於採取了某種先進的監測手段,所以每個工兵營地的人數c國都掌握的一清二楚,每個工兵營地的人數都有可能發生...