線段樹總結

2021-07-15 12:45:40 字數 1401 閱讀 5576

解決的題目:對區間所對應的一些資料進行修改,查詢。

基本步驟:先建樹,然後插入資料,然後更新,查詢。

關鍵部分:用線段樹解題,關鍵是要想清楚每個節點要存哪些資訊以及這些資訊如何高效更新,維護,查詢。

不要一更新就更新到葉子節點,那樣更新效率最壞就可能變成o(n)的了。

建樹的方式:

1)陣列 

若根節點下標為0。假設線段樹上某節點下標為i, 則:左子節點下標為 i *2+1,右子節點下標為 i*2+2

如果用一維陣列存放線段樹,且根節點區間[1,n]。那麼

->使用左右節點指標,則陣列需要有2n-1個元素

->不使用左右節點指標,則陣列需要有:2*2^ [log2n] -1個元素 ([log2n]向上取整)2*2^ [log2n] -1 <= 4n -1 , 實際運用時常可以更小,可嘗試 3n

struct cnode

}tree[maxn*3]; //3*n就夠了

或者

struct cnode

}tree[maxn*2];

更新方式:

#include#include#include#includeusing namespace std;

const int maxn=50000+5;

struct node

}tree[maxn*2];

int nnode;

void buildtree(node *root,int s,int e)

void add(node *root,int s,int e)

if(e<=root->mid) add(root->pleft,s,e);

else if(s>=root->mid+1) add(root->pright,s,e);

else

//更新特殊變數

}void delete(node *root,int s,int e)

if(e<=root->mid) delete(root->pleft,s,e);

else if(s>=root->mid+1) delete(root->pright,s,e);

else

//更新特殊變數

}

其中結點中的特別變數要特別注意:

1)要儲存求題目相關的資料

2)要方便區間合併   如,poj 3667,其中儲存的leftmax和rightlen就是用來方便在合併區間的時候更新maxlen

3)為了加快速度,常常放置乙個標誌,不然就是o(n)複雜度  如poj 3667 中的occupied標誌

注意由於3),所以常常不能更新到葉子結點,所以在用資料的時候要根據標記更新其他資料

線段樹總結

線段樹總結 線段樹的原理就是每乙個區間都可以被分成若干個不相交連續區間 重要 線段樹維護的資料 1.自身結構的資料 比如 左兒子 右兒子的編號 2.懶惰標記 整段區間都變成乙個值 或者將要進行什麼操作 根據每次操作的型別 把操作的區間分成若干個不連續的區間 然後把操作的標記賦值給相應的區間 3.答案...

線段樹總結

線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為n,即整...

線段樹總結

線段樹能解決哪些問題 下面給出線段樹的幾個應用 1 有一列數,初始值全部為0。每次可以進行以下三種操作中的一種 a.給指定區間的每個數加上乙個特定值 b.將指定區間的所有數置成乙個統一的值 c.詢問乙個區間上的最小值 最大值 所有數的和。給出一系列a.b.操作後,輸出c的結果。問題分析 這個是典型的...