線段樹小結

2021-06-22 19:15:40 字數 1537 閱讀 8331

實際上還是稱為區間樹更好理解一些。

樹:是一棵樹,而且是一棵二叉樹。

線段:樹上的每個節點對應於乙個線段(還是叫「區間」更容易理解,區間的起點和終點通常為整數)

同一層的節點所代表的區間,相互不會重疊。同一層節點所代表的區間,加起來是個連續的區間。

葉子節點的區間是單位長度,不能再分了。

線段樹的深度不超過log2(n)+1(向上取整,n是根節點對應區間的長度)。

線段樹上,任意乙個區間被分解後得到的「終止節點」數目都是log(n)量級。

線段樹上更新葉子節點和進行區間分解時間複雜度都是o(log(n))的。

這些結論為線段樹能在o(log(n))的時間內完成插入資料,更新資料、查詢、統計等工作,提供了理論依據。

非葉子節點可以放和,最值,型別,狀態,空間容量(一般用於離散化之後)。

1.結構體定義

struct node

}node[max*3]; //max視情況而定

關於max,

有時需要進行離散化處理,一般是qsort後開乙個很大的陣列儲存i++,進行對映;

有時候可能並不是題目給的那個明顯的n,而是需要輸入update的個數;  例如杭電2795;

總而言之,這一切的目的都是把max減到最小;

2.建樹

void build(int i,int l,int r)

3.更新

void update(int i,int l,int r,int c)

{ if(node[i].left==l&&node[i].right==r)

node[i].w+=c;

if(node[i].mid()>=r) update(i*2,l,r,c);

else if(node[i].mid()

build和update以void格式時都有乙個回溯功能,可以用起來減少步驟;例如build用於區域求和;update用於區段的更新;

if(node[i+i].w&&node[i+i+1].w) node[i].w=1;

不要一更新就更新到葉子節點,那樣更新效率最壞就可能變成o(n)的了!有些甚至要把資訊全部累計在非葉子節點,最後從某個葉子節點返回上去進行統計;

4.查詢

int query(int i,int l,int r)

{ if(node[i].left==l&&node[i].right==r) return node[i].w;

if(node[i].mid()>=r) return query(i*2,l,r);

else if(node[i].mid()

有些關於先後問題例如排隊poj2828,覆蓋poj2825,可以先從後而前考慮,因為後面的都是可以確定的;

當給你的某個值n比較小的時候,可能是給你遍歷的可能性;

線段樹還有區間合併和lazy標記需要拓展。

當然很多難題關於線段樹和其他知識點(例如數論)的結合就只能憑能力了。

下面**有點資料還不錯。

線段樹小結

按照牛的部落格寫了幾道題,刷了一周效果不錯 1.複習鞏固了以前的知識 2.還有改正了一些寫線段樹毛病 3.改正了在弱資料的影響下的錯誤方法ac的題目 4.還學到了線段樹新的型別題 總體效果不錯,總結一下 poj 2892 最直觀的是平衡樹,用樹狀陣列的findk的功能更酷一些,線段樹找第k小也可以,...

線段樹小結

線段樹是一顆二叉樹,每乙個結點維護一段區間。因為是二叉樹,所以可以用p 2表示p的左兒子,p 2 1表示p的右兒子。struct node t maxn 2 線段樹要開四倍空間給定長度為n的陣列a 下標從1開始 對區間 1,n 上的值建一顆線段樹。define lson p 2 define rso...

線段樹小結

線段樹基本概念 線段樹結構 線段樹和區間 線段樹性質 向上取整 這樣在進行更新查詢操作的時候,操作的複雜度就可以為log n 量級 葉子節點的數目和根節點表示的區間長度相同 若葉子節點的數目為n,則線段樹的總節點數目為2 n 1。因為線段樹的節點要麼是0度,要麼為2度,根據二叉樹的性質可知。線段樹操...