1. 程式人生 > >線段樹模板(陣列實現)

線段樹模板(陣列實現)

 首先是基本定義環節

因為線段樹左子節點和右子節點在建構函式的時候比較常用 我們就把這兩個語句簡化一下;

#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);//更改一個值之後 別忘記對整個線段樹進行更新。
}

 以上就是一個模板(感覺寫的比較簡陋)可以用來改造一下。

還可以用結構體來做,這種方法不是唯一的,只是我個人比較喜歡。