線段樹,顧名思義,是根據線段建成的樹。每乙個節點都可以是線段。對於單點查詢,區間查詢,單點更新,區間更新都是o(logn)級別的,所以對於大多數區間操作比較大的題,都可以用線段樹解決。
0.性質
對於每乙個非葉子節點下標為i的節點,它的左兒子的下標必定為i<<1,右兒子的下標必定為i<<1|1.
1.定義
const int maxn = 100005;//線段最大長度
struct nodetree[maxn<<2];//一般是開4倍,但是聽大牛說最多只有3點幾倍
2.建樹
void buildtree(int i,int left,int right)//當前節點的下標及左右端點的座標
int mid=(left+right)>>1;
buildtree(i<<1,left,mid);//折半向左右遞迴建樹
buildtree(i<<1|1,mid+1,right);
}
3.區間查詢
int query(int i,int left,int right)//當前區間的下標和需要查詢的左右端點
int mid=(tree[i].l+tree[i].r)>>1;
if(pos<=mid)modi(i<<1,pos,v);//分別向左右子節點查詢
if(mid
小結:以上就是線段樹最基礎的實現,可以做到單點更新,區間查詢。初學線段樹,重點就是要體會遞迴的思想。
5.區間更新
這個是初學者的一道坎,學會了這個,才算踏入了線段樹的大門。我們需要用到乙個標記,又叫lazytag,看名字就知道,這是乙個很懶的標記,那麼這個標記是用來幹什麼的呢?我們稍後再講。首先我們來討論一下區間更新的時間複雜度。很容易想到,如果我們把區間看做乙個乙個的點,那麼只需要乙個迴圈遍歷所有的點然後對於每乙個點單點更新即可,那麼時間複雜度是多少呢?對於長度為length的區間更新,這樣做的時間複雜度為o(length*logn)如果對於多次長度很大的查詢,這樣做顯然很笨重,那麼這個時候我們就需要用到lazytag了。我們首先在我們最開始定義的結構體中加上乙個成員tag,然後在函式buildtree裡面加上它的初始化,一般的,我們初始化為0,但是對於具體情況還是要具體分析,不能一味的套模板。
void pushdown(int st)
}void update(int i,int left,int right,int v)
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(left<=mid)update(i<<1,left,right,v);//左右向左右子節點遞迴
if(mid
6.區間合併
從這個地方開始就有點困難了,一般的線段樹只能對給定的區間進行操作,但是如果我們需要查詢滿足某種需要的最大區間呢?那麼我們就需要對具有相同性質的區間進行合併。我們一般是向我們定義的結構體中新增三個成員,lsum,rsum,msum。這三個成員分別表示當前區間從左,右端點開始滿足條件的最大長度和整個區間滿足條件的最大長度。
對於子節點,我們可以很容易的判斷出它是否滿足條件,那麼我們就從子節點向上更新即可,例如:
void pushup(int i,int len)//更新的節點下標和更新的區間長度
當然,區間合併也不是直接套用模板就行的,我們需要對具體問題進行分析,才能確定如何進行區間合併。
7.掃瞄線
這個一般是和離散化聯絡起來的,想象出乙個線,沿著乙個方向掃過去。一般都是與離散化的方向垂直。思考清楚然後注意一下資料突變的點就沒什麼難的了。
(這個東西沒有什麼固定的套路(可能是因為我太弱不知道),還是需要多寫,熟練了就好)
總結:線段樹雖然不算高階資料結構,但是很好用,能夠解決很多與區間有關的問題,因為它優秀的時間複雜度,熟練掌握它能加深您對遞迴和二叉樹儲存的理解。當然,以上這些並不是線段樹的全部,如果您熟練掌握了以上線段樹的技巧之後,還意猶未盡的話,您可以去看看《【zkw線段樹講稿】統計的力量-線段樹》,在那個裡面,我感覺線段樹的性質被淋漓盡致地展現出來,十分精彩。
線段樹(一) 點修改
動態範圍最小值問題。給出乙個有 n 個元素的陣列 a 1,a 2,a n 你的任務是設計乙個資料結構,支援以下兩種操作 如果還是使用 sparse table 演算法,每次 update 操作都需要重新計算 d 陣列,時間無法承受。為了解決這個問題,這裡介紹一種靈活的資料結構 線段樹 segment...
關於Treap平衡樹的一點總結
一種好用的資料結構,支援插入 insert 刪除 remove 查前驅 pre 後繼 suf 查樹的排名 get rank by val 據排名查數 getvalbyrank 二叉樹,點帶權,左子樹上的點都比根小,右子樹上的點都比根大。但是,如果插入的是乙個單調的序列,每次對樹進行檢索操作都是 o ...
pushmail的一點總結
從push方法上說有ip push和sms push。ip push就是讓手機始終握著gprs,從而有個ip,讓mail server和手機之間始終有個通路,這樣server一旦有郵件就馬上通過ip push到手機終端上了。sms push就是mail server有郵件了,通知運營商push個簡訊...