Aralık güncelleme + ikili dizinli ağaçlarla aralık sorgusu


10

İkili dizinlenmiş ağaçların (fenwick ağaçları) hem aralık sorgularını hem de aralık güncellemelerini işlemek için nasıl değiştirilebileceğini anlamaya çalışıyorum.

Aşağıdaki kaynakları buldum:

http://kartikkukreja.wordpress.com/2013/12/02/range-updates-with-bit-fenwick-tree/ http://programmingcontests.quora.com/Tutorial-Range-Updates-in-Fenwick-Tree http :? //apps.topcoder.com/forums/ modülü = Konu & threadID = 756271 & start = 0 & mc = 4 # 1579597

Ama hepsini okuduktan sonra bile, ikinci ikili endekslenmiş ağacın amacının ne olduğunu veya ne yaptığını anlayamadım.

Birisi bana ikili dizinli ağacın bunları işlemek için nasıl değiştirildiğini açıklayabilir mi?

Yanıtlar:


9

Diyelim ki boş bir diziniz var:

0  0  0  0  0  0  0  0  0  0  (array)
0  0  0  0  0  0  0  0  0  0  (cumulative sums)

Ve +5 ila [3..7] arasında bir aralık güncellemesi yapmak istediniz:

0  0  0  5  5  5  5  5  0  0  (array)
0  0  0  5 10 15 20 25 25 25  (desired cumulative sums)

İstenilen toplamları 2 ikili endekslenmiş ağaç kullanarak nasıl saklayabilirsiniz?

Hüner, birikimli toplamın içeriklerinden hesaplandığı BIT1 ve BIT2 olmak üzere iki ikili endekslenmiş ağaç kullanmaktır. Bu örnekte, iki ağaçta depolayacağımız şey şudur:

0   0   0   5   5   5   5   5   0   0  (BIT1)
0   0   0  10  10  10  10  10 -25 -25  (BIT2)

Bulmak için şunu sum[i]hesaplarsınız:

sum[i] = BIT1[i] * i - BIT2[i]

Örneğin:

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

Önceki aralık güncellemesi için istenen BIT1 ve BIT2 değerlerine ulaşmak için 3 aralık güncellemesi yaparız:

  • BIT1 için endeks 3..7'ye +5 aralığında bir güncelleme yapmamız gerekiyor.

  • BIT2 için endeks 3..7'ye +10 aralığında bir güncelleme yapmamız gerekiyor.

  • BIT2 için -25 endeksleri 8..9'a kadar bir aralık güncellemesi yapmamız gerekiyor.

Şimdi bir dönüşüm daha yapalım. Yukarıda BIT1 ve BIT2 için gösterilen değerleri depolamak yerine, aslında toplamlarını saklıyoruz. Bu, toplu toplamlarda 4 güncelleme yaparak yukarıdaki 3 aralık güncellemelerini yapmamızı sağlar:

BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35

Genel olarak, [i..j] aralığına v değeri ekleme algoritması şöyle olur:

BIT1sum[i]   += v
BIT1sum[j+1] -= v
BIT2sum[i]   += v * (i-1)
BIT2sum[j+1] -= v * j

burada + = ve - = sözdizimi basitçe BIT kümülatif toplam veri yapısını bu dizinde pozitif veya negatif bir değerle güncellemek anlamına gelir. Bir dizindeki BIT birikimli toplamını güncelleştirdiğinizde, bu dizinin sağındaki tüm dizinleri dolaylı olarak etkilediğini unutmayın. Örneğin:

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])

Fenwick ağaçları toplamları ikili bir ağaçta saklar. Yukarıda gösterilen güncellemeleri Fenwick ağacına zamanında yapmak kolaydır .O(logn)


BIT2'yi yaratma ve sonra sahip olma konusundaki ilk motivasyonunuz neydi sum[i] = BIT1[i] * i - BIT2[i]? İşe yarıyor gibi görünüyor ama çok keyfi görünüyor ... buna hangi içgörü gelmenizi sağlıyor?
1110101001

3
Bu algoritmayı icat etmedim. Tıpkı senin gibi okudum. Ancak dikkat edilmesi gereken bir nokta, bir aralık güncellemesi eklediğinizde, kümülatif toplamlarınızın artan bir sıra haline gelmesidir (5, 10, 15, 20, ...). BIT'ler bunun gibi artan sekansları depolamaz. Ancak BIT'de bir sabit (5) saklarsanız ve BIT değerini dizinle çarparsanız, tam da istediğiniz gibi artan bir sıra elde edersiniz. Ancak, dizinin başlangıcını ve sonunu düzeltmeniz gerekir. İkinci ağaç bunun için.
JS1

Genel olarak iyi, ama "BIT1 ve BIT2 için yukarıda gösterilen değerleri depolamak yerine, aslında toplamlarını saklıyoruz" yazdığınızı kafa karıştırıcı buldum - aslında tam tersini yaptığınızı söyleyebilirim, yani deltaları depolayın .
j_random_hacker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.