Supponiamo di avere un array vuoto:
0 0 0 0 0 0 0 0 0 0 (array)
0 0 0 0 0 0 0 0 0 0 (cumulative sums)
E volevi fare un aggiornamento della gamma da +5 a [3..7]:
0 0 0 5 5 5 5 5 0 0 (array)
0 0 0 5 10 15 20 25 25 25 (desired cumulative sums)
Come è possibile memorizzare le somme cumulative desiderate utilizzando 2 alberi indicizzati binari?
Il trucco è utilizzare due alberi binari indicizzati, BIT1 e BIT2, in cui la somma cumulativa viene calcolata dal loro contenuto. In questo esempio, ecco cosa memorizzeremmo nei due alberi:
0 0 0 5 5 5 5 5 0 0 (BIT1)
0 0 0 10 10 10 10 10 -25 -25 (BIT2)
Per trovare sum[i]
, calcola questo:
sum[i] = BIT1[i] * i - BIT2[i]
Per esempio:
sum[2] = 0*2 - 0 = 0
sum[3] = 5*3 - 10 = 5
sum[4] = 5*4 - 10 = 10
...
sum[7] = 5*7 - 10 = 25
sum[8] = 0*8 - (-25) = 25
sum[9] = 0*9 - (-25) = 25
Per ottenere i valori BIT1 e BIT2 desiderati per l'aggiornamento di intervallo precedente, eseguiamo 3 aggiornamenti di intervallo:
Dobbiamo fare un aggiornamento di intervallo di +5 agli indici 3..7 per BIT1.
Dobbiamo fare un aggiornamento di intervallo di +10 agli indici 3..7 per BIT2.
Dobbiamo fare un aggiornamento di intervallo da -25 agli indici 8..9 per BIT2.
Ora facciamo un'altra trasformazione. Invece di memorizzare i valori mostrati sopra per BIT1 e BIT2, archiviamo effettivamente le loro somme cumulative. Questo ci consente di effettuare i 3 aggiornamenti di intervallo sopra apportando 4 aggiornamenti alle somme cumulative:
BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35
In generale, l'algoritmo per aggiungere un valore v a un intervallo [i..j] sarebbe:
BIT1sum[i] += v
BIT1sum[j+1] -= v
BIT2sum[i] += v * (i-1)
BIT2sum[j+1] -= v * j
dove la sintassi + = e - = significa semplicemente aggiornare la struttura dei dati della somma cumulativa BIT con un valore positivo o negativo in quell'indice. Si noti che quando si aggiorna la somma cumulativa BIT in un indice, ciò influisce implicitamente su tutti gli indici a destra di tale indice. Per esempio:
0 0 0 0 0 0 0 0 0 0 (original)
BITsum[3] += 5
0 0 0 5 5 5 5 5 5 5 (after updating [3])
BITsum[8] -= 5
0 0 0 5 5 5 5 5 0 0 (after updating [8])
Gli alberi di Fenwick immagazzinano somme in un albero binario. È facile eseguire gli aggiornamenti mostrati sopra su un albero Fenwick, in tempo .O ( logn )
sum[i] = BIT1[i] * i - BIT2[i]
? Sembra funzionare ma sembra così arbitrario ... quale intuizione ti permette di arrivare a questo?