여기에서는 처음에 모든 요소가 0인 크기 n의 배열이 제공됩니다. 여기에 수행해야 하는 몇 가지 쿼리가 있습니다. 쿼리에는 두 가지 유형이 있습니다 -
-
업데이트(l,r, 값) - 인덱스 l에서 r 사이에 있는 배열의 요소에 값을 추가합니다. 예를 들어, update(2, 4, 5)는 인덱스 4와 5의 요소에 요소 2를 배치하여 배열을 업데이트합니다.
-
getRangeSum(l, r) − l에서 r까지 요소 범위 내 요소의 합을 찾습니다. 예를 들어, getRangeSum(4, 7)은 인덱스가 4, 5, 6, 7인 모든 요소의 합을 찾습니다.
문제를 이해하기 위해 예를 들어 보겠습니다.
입력
n = 7 , arr[7] = {0,0,0,0,0,0,0} Q1 = update(3, 6, 4) Q2 = update(0, 4, 2) Q3 = Sum(2, 5)
출력
10
설명
Solving queries: Q1 - update(3, 6, 4) = {0, 0, 0, 4, 4, 4, 4} Q2 - update(0, 4, 2) = {2, 2, 2, 2, 2, 4, 4} Q3 - sum(2, 5) = 2+2+2+4 = 10
이 문제를 해결하기 위해 순진한 접근 방식은 각 업데이트 쿼리에서 배열을 업데이트한 다음 합계를 찾는 것이지만 이것은 그다지 효과적이지 않으므로 문제를 해결하는 더 효과적인 접근 방식을 알아보겠습니다.
업데이트 쿼리가 합계 쿼리에 미치는 영향을 살펴보겠습니다. 합계 쿼리는 sum[l,r] 형식이며, 이를 sum[0,k] 형식의 합계 쿼리로 분할한 다음 합계에서 하한까지의 합계에서 하한까지의 합계를 뺍니다.
sum[l,r] = sum[0,r] - sum[0,l]
따라서 sum[0,k]의 효과는 sum[l,r]에 반영됩니다. 합계 변수 k는 상대 값에 따라 3개의 다른 영역에 있으며 업데이트 쿼리의 범위 [l,r]입니다.
지역 1 − k는 o와 l 사이에 있습니다. 즉, 0
이 경우 업데이트 쿼리는 합계 쿼리에 영향을 미치지 않습니다.
지역 2 − k는 l과 r 사이에 있습니다. 즉, l ≤ k ≤ r
이 경우 합계 쿼리는 l에서 k까지의 값을 포함합니다.
지역 3 - k는 r보다 큽니다. 즉, k>r
이 경우 합계 쿼리는 l에서 r 사이의 모든 값을 포함합니다.
이제 Range Update 및 Range 쿼리를 해결하는 프로그램을 살펴보겠습니다.
//범위 업데이트 및 범위 쿼리를 해결하는 프로그램예시
#include <bits/stdc++.h>
using namespace std;
int getSum(int BITree[], int i){
int sum = 0;
i++;
while (i>0) {
sum += BITree[i];
i -= i & (-i);
}
return sum;
}
void updateBITree(int BITree[], int n, int i, int val) {
i = i + 1;
while (i <= n) {
BITree[i] += val;
i += i & (-i);
}
}
void update(int BITTree1[], int BITTree2[], int n, int l, int r, int value) {
updateBITree(BITTree1,n,l,value);
updateBITree(BITTree1,n,r+1,-value);
updateBITree(BITTree2,n,l,value*(l-1));
updateBITree(BITTree2,n,r+1,-value*r);
}
int sum(int x, int BITTree1[], int BITTree2[]) {
return (getSum(BITTree1, x) * x) - getSum(BITTree2, x);
}
int getRangeSum(int l, int r, int BITTree1[], int BITTree2[]) {
return sum(r, BITTree1, BITTree2) - sum(l-1, BITTree1, BITTree2);
}
int *createBITree(int n) {
int *BITree = new int[n+1];
for (int i=1; i<=n; i++)
BITree[i] = 0;
return BITree;
}
int main(){
int n = 7;
int *BITTree1, *BITTree2;
BITTree1 = createBITree(n);
BITTree2 = createBITree(n);
update(BITTree1,BITTree2,n,3,6,9);
update(BITTree1,BITTree2,n, 0, 4, 5);
cout<<"The output of sum query after applying all update queries is \t" <<getRangeSum(1,5,BITTree1,BITTree2);
return 0;
}
출력
The output of sum query after applying all update queries is