線段樹模板(陣列實現)
阿新 • • 發佈:2018-11-06
首先是基本定義環節
因為線段樹左子節點和右子節點在建構函式的時候比較常用 我們就把這兩個語句簡化一下;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn=5008;
int num[maxn<<2];
之後就是一個更新函式 常用於線段樹某處更改數值之後
void pushup(int rt)//更新函式 { num[rt] = num[rt << 1] + num[rt << 1 | 1];//求區間和 num[rt] = max /*min*/ (num[rt << 1] , num[rt << 1 | 1]);//求區間最大最小值 /* 還有很多種不同操作,根據題目要求可以在這裡改變,此函式是讓整個線段樹得以維護的關鍵 有了這個函式不斷地更新陣列的數值,線段樹才得以實現 */ }
接下來便是基本的初始化
void build( int l, int r, int rt)//選擇建立的範圍(l,r) 選擇根節點 rt
{
num[rt] = 0;
if( l == r) return;
int m = (l + r) >> 1;
build(lson);//用遞迴的方法
build(rson);
}
之後是詢問函式 用來求區間內最大值、最小值、區間和或者其他什麼奇奇怪怪和區間有關的東西 (不同需求要不同改造)
int qurey( int L, int R, int l, int r, int rt)//這裡的例子是求區間內之和 當然求別的可以改造 { //(L ,R)代表詢問區間 而 (l,r) 代表整個線段樹區間 ,rt代表根節點 if( L <= l && r <= R)// 如果 L ,R 包裹住了 l,r return num[rt]; int m = (l + r) >> 1; int ans = 0; if(L <= m) ans+=qurey(L, R, lson); if(R > m) ans+=qurey(L, R, rson); return ans; }
之後就是更改某個值了,更改一個值 會對整個線段樹都造成影響,要特別注意更新
void updata( int p, /*int add*/,int l, int r, int rt)//更改操作 { // p為更改的節點 ,l,r仍然代表區間 rt為根節點 也可以選擇對節點更改一些特殊數字 // 如上方的 add if( l == r) { num[rt]++; //num[rt]=add; //num[rt]+=add; return; } int m = ( l + r) >> 1; if(p <= m) updata(p, lson); else updata(p, rson); pushup(rt);//更改一個值之後 別忘記對整個線段樹進行更新。 }
以上就是一個模板(感覺寫的比較簡陋)可以用來改造一下。
還可以用結構體來做,這種方法不是唯一的,只是我個人比較喜歡。