題解 P3372 模板 線段樹1

2022-05-03 17:42:11 字數 1674 閱讀 7811

看了一下題解裡的zkw線段樹,感覺講的不是很清楚啊(可能有清楚的但是我沒翻到,望大佬勿怪)。

決定自己寫一篇。。。希望大家能看明白。。。

zkw線段樹是一種優秀的非遞迴線段樹,速度比普通線段樹快兩道三倍,同時**量不大。

(當然,存在很多線段樹可做zkw不可做的題)

zkw線段樹的核心思路就是先修改葉子,然後從底向上沿著路徑修改。

如果畫一張圖出來整個過程有點像逐漸兩條交回在根節點的鏈。

注意:對於需要維護的區間$[1,n]$,zkw線段樹維護的實際上是$[0,n+1]$。

建樹

1 inline void

build(ll n)

bit表示的底層的大小,我們需要先預處理出這個全域性變數。

然後我們就可以先把葉子的值全部讀入。

讀入之後就順著葉子向上走,更新上面的節點。

這一段**沒有什麼複雜的地方。

更新

1 inline void

update(ll l,ll r,ll val)

8for(;s;s>>=1,t>>=1)tree[s]+=val*ln,tree[t]+=val*rn;

9 }

更新操作稍微比建樹複雜一點。

s和t就是先前提到的兩條鏈,當然準確地說,它們的軌跡才是那兩條鏈。

ln,rn表示的是當前節點的長度(也就是s,t的長度)。

x表示的是s和t中間這一坨的長度。

然後也是一樣的自底向上,每一次先更新兩邊,然後再判斷該更新左兒子還是右兒子。

查詢

1

inline ll query(ll l,ll r)

9for(;s;s>>=1,t>>=1)ans+=tag[s]*ln,ans+=tag[t]*rn;

10return

ans;

11 }

查詢操作和更新一樣,沒什麼好講的。

不開o2跑了511ms,比普通線段樹的760+ms快很多(可能是我寫醜了)

完整**如下:

1 #include2

using

namespace

std;

3 typedef unsigned long

long

ll;4

const ll n=100100;5

ll n,m;

6ll op,x,y,z;

7ll a[n];

8ll bit;

9 ll tree[n<<2],tag[n<<2

];10 inline void

build(ll n)

16 inline void

update(ll l,ll r,ll val)

23for(;s;s>>=1,t>>=1)tree[s]+=val*ln,tree[t]+=val*rn;24}

25inline ll query(ll l,ll r)

33for(;s;s>>=1,t>>=1)ans+=tag[s]*ln,ans+=tag[t]*rn;

34return

ans;35}

36int

main()

45 }

題解 P3372 模板 線段樹 1

題目 剛剛學了樹狀陣列的區間加法和區間求和操作,就用來水掉這題了 本篇適合學會樹狀陣列的人群 前置芝士 普通樹狀陣列 差分樹狀陣列 學過樹狀陣列的人都知道,我們對於乙個陣列,進行處理後,就可以在 o log n 的時間內進行單點修改和區間求和 假設對於陣列 a n 我們用樹狀陣列的方法處理後,就可以...

P3372 模板 線段樹 1

線段樹學習 這個題來看,線段樹分為建樹,更新,查詢。1.建樹 void build ll p,ll l,ll r ll mid l r 1 build lson p l,mid build rson p mid 1,r push up sum p void push up sum ll p 這段 的...

P3372 模板 線段樹 1

題 include includeusing namespace std typedef long long ll ll n,m,ans,x,y,op,val 因為下面有的函式需要用到x,y,val值,懶得傳參,故直接寫為全域性變數 const int n 100000 struct nodetre...