線段樹的一點總結

2021-07-15 19:27:35 字數 2042 閱讀 6290

線段樹,顧名思義,是根據線段建成的樹。每乙個節點都可以是線段。對於單點查詢,區間查詢,單點更新,區間更新都是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個簡訊...