線段樹 模板 例題

2022-07-15 14:12:15 字數 1707 閱讀 8458

模板

區間和為例。

ll ls(ll p) 

ll rs(ll p)

void

push_up(ll p)

void

build(ll p,ll l,ll r)

ll mid=(l+r)>>1

; build(ls(p),l,mid);

build(rs(p),mid+1

,r);

push_up(p);

}void

f(ll p,ll l,ll r,ll k)

void

push_down(ll p,ll l,ll r)

void

update(ll nl,ll nr,ll p,ll l,ll r,ll k)

push_down(p,l,r);

ll mid=(l+r)>>1

;

if(nl<=mid) update(nl,nr,ls(p),l,mid,k);

if(nr>mid) update(nl,nr,rs(p),mid+1

,r,k);

push_up(p);

}ll query(ll ql,ll qr,ll p,ll l,ll r)

例題題面

分析

因為數列中的數$\le 10^$,所以最多開方$6$次就可變為$1$。

當乙個數已經等於$0$或$1$時,再開方就沒有意義了(值不變)。

因此當線段樹中某個葉子節點的值為$0$或$1$時,就給它打標記,可以不再操作。

同樣,某個父親節點的兩個子節點都被標記時,也給它打標記。

詳情見**

1 #include2

#define ll long long

3using

namespace

std;

4const

int n=1e5+5;5

intn,m;

6 ll a[n],sum[n<<2];7

bool tag[n<<2];8

inline ll read()

1415 inline int ls(int p)

16 inline int rs(int p)

17void push_up(int

p) 21

void build(int p,int l,int

r) 23

int mid=(l+r)>>1;24

build(ls(p),l,mid);

25 build(rs(p),mid+1

,r);

26push_up(p);27}

28void update(int nl,int nr,int p,int l,int

r) 35

int mid=(l+r)>>1;36

if(nl<=mid) update(nl,nr,ls(p),l,mid);

37if(mid1

,r);

38push_up(p); 39}

40 ll query(int ql,int qr,int p,int l,int

r) 48

49int

main()

60 }

例題 線段樹

1 注意討論不能建樹的情況 nkoj 1321 數列操作問題 時間限制 10000 ms 空間限制 165536 kb 問題描述 假設有一列數 1 i n 支援如下兩種操作 將ak的值加d。k,d是輸入的數 輸出as as 1 at。s,t都是輸入的數,s t 輸入格式 第一行乙個整數n,第二行為n...

線段樹例題

線段樹可以說是每次比賽中必出的題了,但是線段樹好難,我太難了,我上輩子一定是一道線段樹的題。下面是一些基礎線段樹的題目,入門必備。線段樹是一種二叉搜尋樹,將原始資料都存在葉節點,依次表示出每個葉節點的根節點。一般陣列開到葉節點數量的4倍。關於線段樹的例題 hdu1166 敵兵布陣 按照指示來就可以 ...

例題 線段樹 lazy

1 1 lazy思想 對整個結點進行的操作,先在結點上做標記,而並非真正執行,直到根據查詢操作的需要分到下層。2 延遲標記 lazy 如果需要對乙個區間中每乙個葉結點進行操作,我們不妨先別忙著操作,而是在所有大區間上做乙個標記,下一次遇到或要用到時,再進行處理 標記傳遞 達到減少操作次數,提高線段樹...