Segment tree beats on tekniikka, jolla voi ratkaista seuraavantyyppisiä datastruktuuriongelmia:
Kaikissa ongelmissa , on taulukko, jonka alkuarvot on annettu, ja pitää tukea listattuja operaatiota.
Ongelma 1:
- Annettuna , aseta kaikille
- Annettuna , palauta
Ongelma 2:
- Annettuna , aseta kaikille
- Annettuna , aseta kaikille
- Annettuna , palauta
Ongelma 3:
- Annettuna , aseta kaikille
- Annettuna , aseta
- Annettuna , palauta
Ongelma ratkeaa ajassa , ongelma ajassa , missä on suurin mahdollinen arvo, ja ongelma ajassa .
Ideana on muokata standardikoodia laiskalle segmenttipuulle. Seuraava koodi tekee operaation välille :
void rangeApply(int a, int b, int v, int i, int ia, int ib) { if (b <= ia || ib <= a) return; if (a <= ia && ib <= b) apply(i, v); else { int mid = (ia + ib) / 2; rangeApply(a, b, v, 2*i, ia, mid); rangeApply(a, b, v, 2*i+1, mid, ib); update(i); } }
Haluamme korvata ehdon
b <= ia || ib <= a
voimakkaammalla ehdolla, ja ehdon
a <= ia && ib <= b
heikommalla ehdolla.
Esimerkiksi ensimmäisessä ongelmassa, korvaamme ensimmäisen ehdon ehdolla
a <= ib || b <= ia || interval_min[i] >= v
ja toisen ehdolla
a <= ia && ib <= b && interval_second_min[i] > v.
Tässä interval_second_min[i]
on välin pienin arvo, joka on aidosti suurempi kuin interval_min[i]
.
Käytämme vastaavia ehtoja myös toisessa ongelmassa: muutamme ensimmäiseksi ehdoksi
a <= ib || b <= ia || interval_max[i] < v
ja toiseksi ehdoksi
a <= ia && ib <= b && interval_second_max[i] < v.
Ideana on se, että kun kutsumme apply-funktiota, alipuussa johon sitä kutsumme, on vain yhtä arvoa johon operaatio vaikuttaa! Jos tiedämme kuinka monta kertaa tämä arvo esiintyy alipuussa, voimme helposti päivittää välin summan.
Ratkaisun aikavaatimus voidaan todistaa potentiaalifunktiolla. Otetaan seuraava esimerkkitaulukko:
Ensimmäisessä tehtävässä käytämme potentiaalifunktiona arvoa , missä on niiden solmujen määrä segmenttipuussa, missä solmua vastaavan välin minimi on isompi kuin solmun vanhemman välin minimi. Koska , potentiaalifunktion arvo alussa on enintään , ja jokainen operaatio kasvattaa sitä enintään .
Tässä taulukon välien minimit:
Ja solmut, jotka kontributoivat arvoon :
Olkoon pienin epänegatiivinen kokonaisluku, jolla . Olkoon joukoilla . Olkoon joukko arvoista solmun alipuussa, missä jokainen arvo esiintyy enintään kerran. Toisessa tehtävässä käytämme potentiaalina arvoa . Potentiaalifunktion arvo alussa on enintään , ja jokainen operaatio kasvattaa sitä enintään .
Kolmannessa tehtävässä toimii sama potentiaalifunktio kuin ensimmäisessä, mutta välin kasvatus voi kasvattaa potentiaalia .