Use uma árvore de segmentos - uma partição recursiva do intervalo em intervalos menores. Cada intervalo [ a , b ] de suas operações de atualização pode ser particionado em O ( log n ) dos intervalos nessa partição recursiva. Para cada intervalo [ x , y ] de armazenamento:[ 1 , n ][ a , b ]O ( logn )[ x , y]
- O número de intervalos [c ( x , y) que foram aumentados e não diminuídos, de modo que [ x , y ] é um dos intervalos nos quais [ a , b ] é particionado[ a , b ][ x , y][ a , b ]
- O número de células que não são cobertas por subconjuntos particionados de intervalos que estão em [ x , y ] ou menos na recursãou ( x , y)[ x , y]
Então, se é dividido recursivamente em [ x , z ] e [ z + 1 , w ] , temos
u ( x , y ) = { 0 se c ( x , y ) > 0 u ( x , z ) + u ( z + 1 , y ) caso contrário[ x , y][ x , z][ z+ 1 , w ]
u ( x , y) = { 0u ( x , z) + u ( z+ 1 , y)se c ( x , y) > 0de outra forma
para que possamos atualizar cada valor de
em tempo constante quando os outros dados de um intervalo mudam. Cada consulta de suporte pode ser respondida olhando para
u ( 1 , n ) .
u ( x , y)u ( 1 , n )
Para executar uma operação de aumento , particione [ a , b ] em intervalos O ( log n ) , incremente c (( a , b )[ a , b ]O ( logn ) para cada um desses intervalos e use a fórmula acima para recalcular u ( x , y ) para cada um desses intervalos e cada um de seus ancestrais. A operação de diminuição é a mesma com um decremento em vez de um incremento.c ( x , y)u ( x , y)