#include <stdio.h> using ll = long long; #define MAX_N 1000000 size_t N, M, K; ll Arr[MAX_N + 1]; ll Tree[MAX_N * 4]; // @Desc : Arr의 [s, e]의 합으로 세그먼트 트리를 초기화한다. // @Return : node의 값 // @Param // node : 노드 번호 // s : 범위의 시작 // e : 범위의 마지막 ll Init(size_t node, size_t s, size_t e) { // 단말 노드라면 if (s == e) Tree[node] = Arr[s]; // 단말 노드가 아니라면 else { size_t m = (s + e) / 2; // 왼쪽 자식 노드와 오른쪽 자식 노드의 합이다. Tree[node] = Init(node * 2, s, m) + Init(node * 2 + 1, m + 1, e); } return Tree[node]; } // @Desc : Arr[index]의 값이 바뀌었을 때, 세그먼트 트리의 데이터를 갱신한다. // @Param // node : 현재 노드 // s, e : 노드가 담당하고 있는 범위 // index : 바뀌는 위치 // diff : 바뀌는 값 void Update(size_t node, size_t s, size_t e, size_t index, ll diff) { // 해당 노드가 관련이 없을 때 끝낸다. if (index < s || e < index) return; // 값을 갱신한다. Tree[node] += diff; // 단말 노드가 아니라면 자식 노드도 변경한다. if (s != e) { ll m = (s + e) / 2; Update(node * 2, s, m, index, diff); Update(node * 2 + 1, m + 1, e, index, diff); } } // @Desc : Arr의 [l, r] 범위의 합을 구한다. // @Return : Arr[l] + Arr[l + 1] + ... + Arr[r] // @Param // node : 현재 노드 // s, e : 노드가 담당하고 있는 범위 // l, r : 구하고자 하는 범위 ll Sum(size_t node, size_t s, size_t e, size_t l, size_t r) { // 현재 노드와 관련이 없을 때 if (r < s || e < l) return 0; // 현재 노드가 구하고자 하는 범위에 완전히 포함될 때 if (l <= s && e <= r) return Tree[node]; // 그 외에는 자식 노드를 통해서 구한다. ll m = (s + e) / 2; return Sum(node * 2, s, m, l, r) + Sum(node * 2 + 1, m + 1, e, l, r); } int main() { scanf("%lld %lld %lld", &N, &M, &K); for (size_t i = 1; i <= N; i++) scanf("%lld", &Arr[i]); Init(1, 1, N); for (size_t i = 0; i < M + K; i++) { ll a, b, c; scanf("%lld %lld %lld", &a, &b, &c); if (a == 1) { ll diff = c - Arr[b]; Arr[b] = c; Update(1, 1, N, b, diff); } else { printf("%lld\n", Sum(1, 1, N, b, c)); } } } |