การปรับปรุงช่วง + แบบสอบถามช่วงที่มีต้นไม้ที่จัดทำดัชนีไบนารี


10

ฉันพยายามที่จะเข้าใจว่าต้นไม้ดัชนีแบบไบนารี (ต้นไม้ fenwick) สามารถแก้ไขได้เพื่อจัดการแบบสอบถามทั้งช่วงและการปรับปรุงช่วง

ฉันพบแหล่งข้อมูลต่อไปนี้:

http://kartikkukreja.wordpress.com/2013/12/2/range-updates-with-bit-fenwick-tree/ http://programmingcontests.quora.com/Tutorial-Range-Updates-in-Fenwick http : //apps.topcoder.com/forums/ โมดูล = Thread & threadid = 756271 & start = 0 & MC = 4 # 1579597

แต่แม้หลังจากอ่านทั้งหมดฉันก็ไม่สามารถเข้าใจได้ว่าจุดประสงค์ของต้นไม้ดัชนีไบนารีตัวที่สองคืออะไรหรือทำอะไร

มีคนช่วยอธิบายให้ฉันฟังหน่อยได้ไหมว่าต้นไม้แบบดัชนีแบบไบนารีถูกแก้ไขเพื่อจัดการสิ่งเหล่านี้อย่างไร

คำตอบ:


9

สมมติว่าคุณมีอาร์เรย์ที่ว่างเปล่า:

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

และคุณต้องการอัปเดตช่วงจาก +5 เป็น [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)

คุณจะเก็บผลรวมสะสมที่ต้องการโดยใช้ต้นไม้ดัชนี 2 ไบนารีได้อย่างไร

เคล็ดลับคือการใช้ทรีดัชนีแบบไบนารีสองต้นคือ BIT1 และ BIT2 ซึ่งผลรวมสะสมจะถูกคำนวณจากเนื้อหา ในตัวอย่างนี้นี่คือสิ่งที่เราต้องการเก็บไว้ในต้นไม้สองต้น:

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

ในการค้นหาsum[i]คุณคำนวณสิ่งนี้:

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

ตัวอย่างเช่น:

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

เพื่อให้ได้ค่า BIT1 และ BIT2 ที่ต้องการสำหรับการอัพเดทช่วงก่อนหน้านี้เราทำการอัปเดต 3 ช่วง:

  • เราต้องทำการอัปเดตช่วงจาก +5 เป็นดัชนี 3..7 สำหรับ BIT1

  • เราต้องทำการอัปเดตช่วงจาก +10 เป็นดัชนี 3..7 สำหรับ BIT2

  • เราต้องทำการอัปเดตช่วง -25 ถึงดัชนี 8..9 สำหรับ BIT2

ทีนี้ลองทำการแปลงอีกครั้ง แทนที่จะเก็บค่าที่แสดงด้านบนสำหรับ BIT1 และ BIT2 เราจะเก็บผลรวมสะสมจริง ๆ สิ่งนี้ช่วยให้เราทำการอัปเดต 3 ช่วงด้านบนได้โดยทำการอัปเดตผลรวมสะสม 4 รายการ:

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

โดยทั่วไปอัลกอริทึมในการเพิ่มค่า v ลงในช่วง [i..j] จะเป็น:

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

โดยที่ + = และ - = ไวยากรณ์นั้นหมายถึงการปรับปรุงโครงสร้างข้อมูลผลรวมสะสม BIT ด้วยค่าบวกหรือค่าลบที่ดัชนีนั้น โปรดทราบว่าเมื่อคุณอัปเดตผลรวมสะสม BIT ที่ดัชนีจะมีผลกระทบต่อดัชนีทั้งหมดทางด้านขวาของดัชนีนั้นโดยปริยาย ตัวอย่างเช่น:

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

ต้นไม้เฟนวิคเก็บผลรวมไว้ในต้นไม้ไบนารี มันเป็นเรื่องง่ายที่จะทำการอัปเดตที่แสดงด้านบนของต้นไม้ FenwickO(เข้าสู่ระบบn) เวลา.


อะไรคือแรงจูงใจเบื้องต้นของคุณในการสร้าง BIT2 และหลังจากนั้น sum[i] = BIT1[i] * i - BIT2[i] ? ดูเหมือนว่าจะใช้งานได้ แต่ดูเหมือนว่าจะเป็นข้อ จำกัด ... อะไรที่ทำให้คุณเข้าใจได้
1110101001

3
ฉันไม่ได้คิดค้นอัลกอริทึมนี้ ฉันอ่านมันเหมือนที่คุณทำ แต่สิ่งหนึ่งที่ควรสังเกตคือเมื่อคุณเพิ่มการอัปเดตช่วงจำนวนเงินสะสมของคุณจะกลายเป็นลำดับที่เพิ่มขึ้น (5, 10, 15, 20, ... ) BIT ไม่เก็บลำดับที่เพิ่มขึ้นเช่นนั้น แต่ถ้าคุณเก็บค่าคงที่ (5) ใน BIT และคูณค่า BIT ด้วยดัชนีคุณจะได้ลำดับที่เพิ่มขึ้นเหมือนกับที่คุณต้องการ อย่างไรก็ตามคุณต้องแก้ไขจุดเริ่มต้นและจุดสิ้นสุดของลำดับ นั่นคือสิ่งที่ต้นไม้ต้นที่สองมีไว้สำหรับ
JS1

ดีในทั้ง แต่ผมพบว่ามันทำให้เกิดความสับสนว่าคุณเขียนว่า "แทนการจัดเก็บค่าที่แสดงข้างต้นสำหรับ BIT1 และ BIT2 เราจริงเก็บเงินก้อนสะสมของพวกเขา" - ผมจะบอกว่าคุณเป็นจริงทำตรงข้ามคือการจัดเก็บสันดอน .
j_random_hacker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.