Użyj drzewa segmentów - rekurencyjnej partycji zakresu na mniejsze zakresy. Każdy przedział operacji aktualizacji można podzielić na zakresów w tej partycji rekurencyjnej. Dla każdego zakresu przechowuj:[ a , b ] O ( log n ) [ x , y ][1,n][a,b]O(logn)[x,y]
- Liczba w odstępach , że została zwiększona, a nie zmniejszyła się w taki sposób, to jeden z przedziałów, w którym rozdziela[ a , b ] [ x , y ] [ a , b ]c(x,y)[a,b][x,y][a,b]
- Liczba komórek, które nie są objęte podzielonymi podzbiorami przedziałów o wartości lub niższej w rekurencji[ x , y ]u(x,y)[x,y]
Następnie, jeśli jest rekurencyjnie podzielony na i , mamy
dzięki czemu możemy aktualizować każdą wartość w stałym czasie, gdy inne dane dla zakres się zmienia. Na każde zapytanie wsparcia można odpowiedzieć, patrząc na .[ x , z ] [ z + 1 , w ] u ( x , y ) = { 0, jeśli c ( x , y ) > 0 u ( x , z ) + u ( z + 1 , y ) w przeciwnym razie u ( x , y ) u ( 1[x,y][x,z][z+1,w]
u(x,y)={0u(x,z)+u(z+1,y)if c(x,y)>0otherwise
u(x,y)u(1,n)
Aby wykonać operację zwiększenia , podziel na zakresy , zwiększ dla każdego z tych zakresów i użyj powyższego wzoru, aby ponownie obliczyć dla każdego z tych zakresów i każdego z ich przodków. Operacja zmniejszania jest taka sama z dekrementacją zamiast inkrementem.[ a , b ] O ( log n ) c ( x , y ) u ( x , y )(a,b)[a,b]O(logn)c(x,y)u(x,y)