本來以為是和zkw單點修改之類的簡單技巧,但是今天卡常的時候學習了一下發現有點離譜。rx
tr_x
trx
,表示maxf
ax
−maxx
\max_ - \max_
maxfax
−maxx
,也就是線段樹上乙個節點和他父親區間最大值的差分,我們現在可以知道乙個線段樹上乙個整區間的最大值就是他到根的和。
那麼我們求區間最大值,就是對於乙個區間分成的logn
\log n
logn
個整區間分別求到根的和。
可以通過簡單的技巧在極小常數的o
(logn
)o(\log n)
o(logn
)內完成,具體看**。
區間加x
xx,那麼我們找到區間最左邊的點的葉子和最右邊的點的葉子。
然後一起往上爬,如果左邊的那個點是父親的左兒子,那麼右兒子的trtr
tr需要加上x
xx。(右邊同理)
但是這樣修改之後父親的最大值可能會變化,他的trtr
tr就不對了,那麼我們需要維護父親的trtr
tr,具體看**。
所以這種線段樹式的差分使得我們可以拋棄懶標記,從而使常數和樹狀陣列一樣優秀。
打懶標記的線段樹在比較差的評測機上是一秒跑不過1e6的,這也是寫這篇部落格的目的,大概常數是一般線段樹的3
5\frac 35
53
c od
e\mathcal code
code
#define lc u<<1
#define rc lc|1
int mx[maxn <<2]
, ans[maxn]
, m;
inline
void
upd(
int u)
void
add(
int l,
int r)
for(
;l !=
1;l >>=1)
upd(l >>1)
;}intqry
(int l,
int r)
int ans =
max(la + mx[l]
, ra + mx[r]);
for(
;l >1;
) ans +
= mx[l >>=1]
;return ans;
}
線段樹 區間加區間乘
給出序列 a1,a2,an 0 ai 109 有關序列的四種操作 1.al,al 1,ar 1 l r n 加上 x 103 x 103 2.al,al 1,ar 1 l r n 乘上 x 103 x 103 3.al,al 1,ar 1 l r n 變成 x al,x al 1 x ar 103 ...
線段樹,區間最值
codeforces 91b queue 線段樹,區間最值 題意是,對於給定區間內的每個元素,要求求出離他最遠的那個元素之間的距離。可以維護乙個線段樹的最小值,每次對於乙個元素,查詢其最右邊的元素的位置。include include include includeusing namespace s...
線段樹動態開點區間加區間求和
陝西師範大學第七屆程式設計競賽網路同步賽 h.萬惡的柯怡 保證葉子節點被完整的覆蓋,需要開節點,就把左右兒子都開出來,其餘和普通線段樹一樣。用結構體內部函式,記憶體不足,第一次遇見本地問題不嚴重 不明嚼慄?include typedef long long ll const int n 400001...