Oproti obyčajnému intervalovému stromu potrebujeme urobiť nasledovné zmeny:
Vždy, keď ide nejaký vrchol delegovať robotu na svojich synov, musí si skontrolovať, či má niečo v diári (a prípadne im o tom dať vedieť). Na tento účel si môžeme implementovať špeciálnu funkciu propagate(). Keďže synovia by si aj tak iba aktualizovali hodnoty a zapísali požiadavku do diára, nemusíme na nich volať
funkciu určenú na menenie intervalov, ale hodnoty a diáre im môžeme zmeniť priamo my. * Musíme implementovať funkciu na vyhodnocovanie tretieho druhu požiadaviek. To by malo byť pomerne priamočiare.
Keďže vďaka lazy propagation vieme zmeniť interval, nemusíme implementovať zmenu jednotlivých prvkov tak, ako pri štandardnom intervalovom strome. Väčšina kódu až na metódy update a propagate ostáva oproti nelenivému intervalovému stromu nezmenená.
import math
class LazySegmentTree:
# vytvor intervalovy strom z daneho pola p
def __init__(self, p):
self.n = 2 ** math.ceil(math.log2(len(p)))
self.values = [0] * (2 * self.n)
self.lazy = [1] * (2 * self.n)
for i in range(len(p)):
self.values[i + self.n] = p[i]
for i in range(self.n - 1, 0, -1):
self.values[i] = self.values[i * 2] + self.values[i * 2 + 1]
# sucet na intervale
def query(self, v, i, j, l, r):
if l >= j or r <= i:
return 0
if l <= i and r >= j:
return self.values[v]
self.propagate(v)
mid = (i + j) // 2
return self.query(v * 2, i, mid, l, r) + self.query(v * 2 + 1, mid, j, l, r)
# prenasobenie hodnot na intervale hodnotou h
def update(self, v, i, j, l, r, x):
if l >= j or r <= i:
return
if l <= i and r >= j:
self.lazy[v] *= x
self.values[v] *= x
return
self.propagate(v)
mid = (i + j) // 2
self.update(v * 2, i, mid, l, r, x)
self.update(v * 2 + 1, mid, j, l, r, x)
self.values[v] = self.values[v * 2] + self.values[v * 2 + 1]
# metoda, ktora synom posunie poziadavky, ktore im mali prist uz skor ale bol som lenivy
def propagate(self, v):
self.lazy[v * 2] *= self.lazy[v]
self.values[v * 2] *= self.lazy[v]
self.lazy[v * 2 + 1] *= self.lazy[v]
self.values[v * 2 + 1] *= self.lazy[v]
self.lazy[v] = 1