通過只開需要使用的結點以節省空間。
實現過程就是把點乙個乙個往樹裡面插。
建樹時遞迴進入當前結點的子結點後,若該結點為 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...