이진 색인 트리가있는 범위 업데이트 + 범위 쿼리


10

범위 쿼리 및 범위 업데이트를 처리하기 위해 이진 색인 트리 (fenwick tree)를 수정하는 방법을 이해하려고합니다.

다음과 같은 출처를 찾았습니다.

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/? module = 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 개의 이진 인덱스 트리를 사용하여 원하는 누적 합계를 어떻게 저장할 수 있습니까?

비결은 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 가지 범위 업데이트를 수행합니다.

  • BIT1의 경우 지수 3..7에서 +5의 범위 업데이트를 수행해야합니다.

  • BIT2의 경우 지수 3..7로 +10의 범위 업데이트를 수행해야합니다.

  • BIT2의 경우 지수 8..9에서 -25의 범위 업데이트를 수행해야합니다.

이제 하나 더 변형을하겠습니다. BIT1 및 BIT2에 대해 위에 표시된 값을 저장하는 대신 실제로 누적 합계를 저장합니다. 이를 통해 누적 합계를 4 번 업데이트하여 위의 3 가지 범위 업데이트를 수행 할 수 있습니다.

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

Fenwick 트리는 이진 트리에 합계를 저장합니다. 위에 표시된 업데이트는 시간 에 Fenwick 트리에 쉽게 수행 할 수 있습니다 .O(logn)


BIT2를 만들고 가지고있는 초기 동기는 무엇입니까 sum[i] = BIT1[i] * i - BIT2[i]? 작동하는 것처럼 보이지만 너무 임의적 인 것 같습니다 ...이 통찰력을 얻을 수있는 통찰력은 무엇입니까?
1,110,101,001

3
글쎄, 나는이 알고리즘을 발명하지 않았다. 네가 한 것처럼 읽었 어 그러나 범위 업데이트를 추가하면 누적 합계가 증가하는 시퀀스 (5, 10, 15, 20, ...)가됩니다. BIT는 이와 같이 증가하는 시퀀스를 저장하지 않습니다. 그러나 BIT에 상수 (5)를 저장하고 BIT 값에 인덱스를 곱하면 원하는대로 시퀀스가 ​​증가합니다. 그러나 시퀀스의 시작과 끝을 수정해야합니다. 이것이 두 번째 나무입니다.
JS1

내가 말할 것이다 당신이 실제로 반대를하고있는, 즉, 저장 - 전체에 좋은,하지만 나는 "우리가 실제로 자신의 누적 금액을 저장하는 대신 BIT1 및 BIT2에 대한 위에 표시된 값을 저장하는"당신이 쓴 혼란 발견 델타를 .
j_random_hacker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.