學習筆記 動態開點線段樹

2021-10-23 20:11:28 字數 1761 閱讀 6192

通過只開需要使用的結點以節省空間。

實現過程就是把點乙個乙個往樹裡面插。

建樹時遞迴進入當前結點的子結點後,若該結點為 0 ,即不存在,就開點。

所謂開點即為把當前結點的編號設定為 ++tot 。

這樣處理下來,每個結點的編號顯然是亂序的。

可以 l_son 和 r_son 分別記錄左右子結點的編號,然後讓它們代替普通線段樹的 now*2 和 now*2+1 即可。

需要注意的是,修改時的 now 必須是變參。

下為區間求和**。

#include

#include

#pragma gcc diagnostic error "-std=gnu++11"

#define reg register

using

namespace std;

namespace fast_io

while

(isdigit

(ch)

) x*

=flag;

}template

<

typename conv,

typename..

. args>

inline conv read

(conv &first, args &..

. args)

template

<

typename conv>

inline conv write

(conv x)

if(x>9)

putchar

(x%10+48

);}template

<

typename conv,

typename..

. args>

inline conv write

(conv first, args .

.. args)

}using

namespace fast_io;

const

int maxn=

1e6+5;

int n, m, tot=

0, root=0;

struct segment_tree tree[maxn<<2]

;//更新

void

push_up

(int now)

//區間修改

void

update

(int

&now,

int l,

int r,

int x,

int y,

int val)

int mid=

(l+r)

>>1;

if(x<=mid)

if(y>mid)

push_up

(now);}

//區間查詢

intquery

(int now,

int x,

int y,

int l,

int r)

int res=0;

int mid=

(x+y)

>>1;

if(l<=mid)

if(r>mid)

return res;

}int

main()

for(reg int i=

1; i<=m; i++

)else

}return0;

}

動態開點線段樹 學習筆記

所謂權值線段樹,就是指線段樹記憶體的是權值。好像是廢話。給出一些數,要查詢乙個區間內的數的個數。這時可以用權值線段樹,開個n n為給出的數的最大值 個點的線段樹。然後就能輕鬆的維護了當然樹狀陣列更簡單 為什麼要動態開點呢?當然是因為空間不夠啊。比如還是上面那個例子。加入給出的數的最大值為 10 並且...

動態開點線段樹

前置芝士 眾所周知,普通線段樹空間複雜度是 o n 4 所以當n很大的時候,如果正常的去建一顆線段樹,開4倍n空間顯然會炸記憶體 怎麼辦呢?這個時候,動態開點線段樹出現了。概念 動態開點線段樹是一類特殊的線段樹,與普通的線段樹不同的是,每乙個節點的左右兒子不是該點編號的兩倍和兩倍加一,而是現加出來的...

旅行 樹剖,動態開點線段樹

對每一種教派開一顆線段樹,但是很明顯空間會爆,所以動態開點線段樹,所以空間複雜度降低到nlo gnnlogn nlog n,然後樹剖套線段樹,碼量稍大 include define m 200009 using namespace std intread for isdigit ch ch getc...