線段樹

借鑒數據結構專題——線段樹
例題: 算法訓練 操作格子
線段樹
線段樹與逆序對
線段樹

線段樹的構造

#include <iostream>  
using namespace std;  
  
const int maxind = 256;  
int segTree[maxind * 4 + 10];  
int array[maxind];   
/* 構造函數,得到線段樹 */  
void build(int node, int begin, int end)    
{    
    if (begin == end)    
        segTree[node] = array[begin]; /* 只有一個元素,節點記錄該單元素 */  
    else    
    {     
        /* 遞歸構造左右子樹 */   
        build(2*node, begin, (begin+end)/2);    
        build(2*node+1, (begin+end)/2+1, end);   
           
        /* 回溯時得到當前node節點的線段信息 */    
        if (segTree[2 * node] <= segTree[2 * node + 1])    
            segTree[node] = segTree[2 * node];    
        else    
            segTree[node] = segTree[2 * node + 1];    
    }    
}  
  
int main()  
{  
    array[0] = 1, array[1] = 2,array[2] = 2, array[3] = 4, array[4] = 1, array[5] = 3;  
    build(1, 0, 5);  
    for(int i = 1; i<=20; ++i)  
     cout<< "seg"<< i << "=" <<segTree[i] <<endl;  
    return 0;  
}   

區間查詢

int query(int node, int begin, int end, int left, int right)    
{   
    int p1, p2;    
    
    /*  查詢區間和要求的區間沒有交集  */  
    if (left > end || right < begin)    
        return -1;    
    
    /*  if the current interval is included in  */    
    /*  the query interval return segTree[node]  */  
    if (begin >= left && end <= right)    
        return segTree[node];    
    
    /*  compute the minimum position in the  */  
    /*  left and right part of the interval  */   
    p1 = query(2 * node, begin, (begin + end) / 2, left, right);   
    p2 = query(2 * node + 1, (begin + end) / 2 + 1, end, left, right);    
    
    /*  return the expect value  */   
    if (p1 == -1)    
        return p2;    
    if (p2 == -1)    
        return p1;    
    if (p1 <= p2)    
        return  p1;    
    return  p2;      
}   

單節點的更新

void Updata(int node, int begin, int end, int ind, int add)/*單節點更新*/    
{    
    
    if( begin == end )    
    {    
        segTree[node] += add;    
        return ;    
    }    
    int m = ( left + right ) >> 1;    
    if(ind <= m)    
        Updata(node * 2,left, m, ind, add);    
    else    
        Updata(node * 2 + 1, m + 1, right, ind, add);    
    /*回溯更新父節點*/    
    segTree[node] = min(segTree[node * 2], segTree[node * 2 + 1]);     
         
}   

區間的更新

void Change(node *p, int a, int b) /* 當前考察結點為p,修改區間為(a,b]*/  
   
{  
   
  if (a <= p->Left && p->Right <= b)  
   
  /* 如果當前結點的區間包含在修改區間內*/  
   
  {  
   
     ...... /* 修改當前結點的信息,并標上標記*/  
   
     return;  
   
  }  
   
  Push_Down(p); /* 把當前結點的標記向下傳遞*/  
   
  int mid = (p->Left + p->Right) / 2; /* 計算左右子結點的分隔點 
  
  if (a < mid) Change(p->Lch, a, b); /* 和左孩子有交集,考察左子結點*/  
   
  if (b > mid) Change(p->Rch, a, b); /* 和右孩子有交集,考察右子結點*/  
   
  Update(p); /* 維護當前結點的信息(因為其子結點的信息可能有更改)*/  
   
}  
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容