728x90
반응형

링크

https://www.acmicpc.net/problem/2042

 

2042번: 구간 합 구하기

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄

www.acmicpc.net

해설


사실 이문제는 세그먼트 트리를 이용하거나 펜윅 트리를 이용하면 더욱 빠르게 구할 수 있습니다.

세그먼트 트리를 이용한 방법과 펜윅 트리를 이용한 방법 둘 다 나중에 올리겠습니다.

근데 제가 배우질 않아서 일단 full binary tree 를 이용해서 풀었습니다.

 

코드는 간단합니다.

입력수만큼 받고 2^n 까지 나머지를 0으로 채우고 full binary tree 로 만들면 됩니다.

그 후 각 노드들은 하위 2개노드의 합을 적어두고

만약 값이 바뀔경우 해당 노드와 상위 노드의 갑만 수정해주면 됩니다.

 

a ~ b 까지의 합을 구하는 방법은

1. 쪼개고 쪼개다가 최소 단위가 되었을 경우

2. 쪼개던 중 쪼개진 범위가 구해야 하는 범위 안에 다 들어갈 경우

위의 2가지 경우를 모두 더해주면 a ~ b 까지 합을 구할 수 있습니다.

 

코드

#include <iostream>
using namespace std;
int N, M, K, NUM = 1;
long long TABLE[2097152];
long long sum(int _l, int _r, int _a, int _b, int _num) {
if ((_l == _a && _r == _b) || _a == _b)
return TABLE[_num];
int mid_left = (_a + _b - 1) / 2, list_num_left = _num * 2 + 1;
if (_r <= mid_left)
return sum(_l, _r, _a, mid_left, list_num_left);
else if (mid_left < _l)
return sum(_l, _r, mid_left + 1, _b, list_num_left + 1);
else
return sum(_l, mid_left, _a, mid_left, list_num_left) +
sum(mid_left + 1, _r, mid_left + 1, _b, list_num_left + 1);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M >> K;
int finish, start;
while (NUM < N) NUM *= 2;
start = NUM - 1;
finish = start * 2;
for (int i = start; i < start + N; ++i)
cin >> TABLE[i];
for (int i = start + N; i <= finish; ++i) {
TABLE[i] = 0;
}
for (int i = start - 1; i >= 0; --i) {
int num = i * 2 + 1;
TABLE[i] = TABLE[num] + TABLE[num + 1];
}
for (int i = 0; i < M + K; ++i) {
int first, second;
cin >> first >> second;
if (first == 1) {
long long third;
cin >> third;
int number = start + second - 1;
long long gap = third - TABLE[number];
while (true) {
TABLE[number] += gap;
if (number == 0)
break;
number = (number - 1) / 2;
}
}
else {
int third;
cin >> third;
cout << sum(second, third, 1, NUM, 0) << "\n";
}
}
return 0;
}



728x90
반응형

'컴퓨터공학 > 백준' 카테고리의 다른 글

[백준][1103][C++] 게임  (0) 2021.07.07
[백준][1062][C++] 가르침  (0) 2021.07.06
[백준][2580][C++] 스도쿠  (0) 2021.07.04
[백준][1806][C++] 부분합  (0) 2021.07.03
[백준][17298][C++] 오큰수  (0) 2021.07.02

+ Recent posts