線段樹選講

2021-07-05 22:18:56 字數 1924 閱讀 1421

線段樹選講

線段樹是一種二叉搜尋樹

,與區間樹

相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。

對於線段樹中的每乙個非葉子節點

[a,b],它的左兒子表示的區間為[a,(a+b)/2],右兒子表示的區間為[(a+b)/2+1,b]。因此線段樹是平衡二叉樹

,最後的子節點數目為n,即整個線段區間的長度。

使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度

為o(logn)。而未優化的空間複雜度

為2n,因此有時需要離散化讓空間壓縮。

第一初始化:

int tree[maxn];

void buildtree(int left,int right,int rt)

int mid=(left+right)/2;

buildtree(left,mid,rt<<1); //左子區間

buildtree(mid+1,right,rt<<1|1); //右子區間

pushup(rt); //每個區間的值由左右區間的值共同決定(由葉向根計算)

}

第二更新:

單點更新:

單點更新只要更新葉子節點,所以除了改變這個點的值還需要從葉子節點向上更新區間數值

void update(int left,int right,int pos,int change,int rt)

int mid=(left+right)/2;

if(mid>=pos) //如果要更新的點在左子區間

update(left,mid,pos,change,rt<<1);

else //如果要更新的點在右子區間

update(mid+1,right,change,rt<<1|1);

pushup(rt); //向上修正區間值到根節點

}

區間更新:區間更新和單點更新不同,區間更新時除了改變該段區間的值並向上傳遞之外,還需要將其所有子區間更新,

void update(int l,int r,int left,int right,int rt,int change)     //l,r為要求更新區間

這裡比單點更新多了乙個pushdown(),這個函式是在之後的子區間中改變他們對應的值而準備的。

void pushdown(int left,int right,int rt)

}

第三詢問:單點詢問:

int query(int left,int right,int rt,int pos)                       //詢問pos點的值

區間詢問:

int query(int l,int r,int left,int right,int rt)

綜上線段樹的三個功能講完!

樹之習題選講

核心演算法 void solve int prel,int inl,int postl,int n root pre prel post postl n 1 root for i 0 i in inl 1 root break l i r n l 1 solve prel 1,inl,postl,l...

樹狀陣列選講

樹狀陣列 binary indexed tree bit fenwick tree 是乙個查詢和修改複雜度都為log n 的資料結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值 經過簡單修改可以在log n 的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值。樹狀陣列...

CodeChef題目選講

關鍵點 不超過7條 根據咕咕原理,所以答案最少是n 7 n小於49就暴力 隨機化找兩個點判斷直線上的點個數,隨機500次,概率就很高了 法二 點數大於50,答案至少是8 答案一定是7條路之一 隨機找7個點,按照級角序排序,點數大於7的直線就刪去上面的點 之後random不考慮,但是實際上不能真刪除,...