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