zkw線段樹小結

2021-10-10 02:55:11 字數 2223 閱讀 2684

zkw

zkwzk

w線段樹作為迴圈式線段樹具有較小的常數.(其實樹狀陣列本質上就是線段樹…

下標為[1,

n]

[1,n]

[1,n

],預處理乙個2

k>

n2^k>n

2k>n.

然後總空間為2k+

12^

2k+1

.(2 k+

1<4n

2^<4n

2k+1

<4n

)後面令k=2

kk=2^k

k=2k

.那麼乙個葉子x

xx的位置在x+k

x+kx+

k.

for

(x +

= k; x;x /=2

)...

.

直接遍歷到根

因為z kw

zkwzk

w線段樹是自底往上求,所以一般使用標記永久化的tri

ck

trick

trick.

所以如果維護的標記比較繁雜,還是打普通線段樹比較好.

當遇到區間求和和區間修改的時候,我們令l+=

k−1,

r+=k

+1

l+=k-1,r+=k+1

l+=k−1

,r+=

k+1,即變為開區間.(這個是為了和的上傳

當只有區間求和和單點修改的時候,我們可以考慮轉化為左開右閉區間.

乙個區間加是這樣的:

void

add(

int l,

int r,ll x)

for(l +

= r;l/=2

; s[l]

+= l*x)

;}

對應的區間求和:

ll sum

(int l,

int r)

for(l+

=r;l/=2

;ans+

=ad[l]

*l);

return ans;

}

這個在沒有修改的情況下還是很好求的,只要預處理一下就好.

但是如果遇上區間標記呢?(比如區間加

z kw

zkwzk

w在pp

tppt

ppt內有講到乙個核心思想:

標記和值都是相對的數,那麼我們何必同時維護標記和值呢?

為了同化,我們直接差分,這樣取原值我們直接遍歷到根求和即可.

具體地,比方說我們要維護區間min

⁡\min

min:

那麼我們令dmn

[i]=

mn[i

]−mn

[i/2

]dmn[i]=mn[i]-mn[i/2]

dmn[i]

=mn[

i]−m

n[i/

2],m n[

i]

mn[i]

mn[i

]表示區間最小值,**內實際上只保留dmn

dmndm

n.預處理:

for

(int i=

1;i<=n;i++

) mn[i+k]

=a[i]

;for

(int i=k-

1; i;i--

)

對應的區間加應該是這樣的:

void

upd(

int x)

void

add(

int l,

int r,ll x)

for(

;l/=2;

upd(l));

}

求min

⁡\min

min:

int

min(

int l,

int r)

int ans=

min(l+mn[l]

,r+mn[r]);

for(

;l /=2

;) ans +

= mn[l]

;return ans;

}

線段樹和zkw線段樹

好啦,我們就開始說說線段樹吧 線段樹是個支援區間操作和查詢的東東,平時的話還是蠻實用的 下面以最基本的區間加以及查詢區間和為例 線段樹顧名思義就是棵樹嘛,葉子節點是每個基本點,它們所對應的父親就是它們的和,具體如下圖 但是對於這樣的線段樹來說,操作所需的時間是遠達不到我們的要求的 會被t 因為我們會...

鏈結 zkw線段樹

資料結構 走近zkw線段樹 一 資料結構 走近zkw線段樹 二 線段樹的擴充套件之 zkw線段樹 include define lc x x 1 define rc x x 1 1 using namespace std const int maxn 100005 int max int a,int...

ZKW線段樹之旅 1

膜拜zkw神犇。orz。zkw線段樹的思想是直接找到乙個大區間對應的小區間 由於是自底向上的,所以常數很小 統計的力量 其實我覺得,真正難寫的是區間修改 比如現在造一顆線段樹,支援區間求和,區間修改 zkw線段樹有兩種做法 一是維護神奇的字首和的字首和 二是沿用遞迴版線段樹的思路,在區間上打標記,然...