※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 10999번 문제인 구간 합 구하기 2이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/10999

 

10999번: 구간 합 구하기 2

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

www.acmicpc.net

이 문제는 구간 갱신 쿼리가 포함되어 있다.

만약 구간 갱신 쿼리를 구간의 각 점에 대하여 한번씩 실행한다면 그 속도는 매우 느려질 수밖에 없다.

이럴 때에는, 모든 구간에 갱신 명령을 일단 하되, 갱신된 값에 접근이 필요할 때마다 해당 갱신을 실행하는, 지연 전파(lazy propagation)를 이용하여 문제를 해결할 수 있다.

 

이 문제에서 몇몇 구간합은 64비트 정수가 표현할 수 있는 범위를 넘어갈 수 있다.

그러나 오버플로우가 일어났을 때의 덧셈은 기대하는 대로 잘 정의가 되어있고, 이 문제의 쿼리는 정답이 64비트 정수가 표현할 수 있는 범위 내인 구간에서만 질의하므로 걱정할 필요 없이 평소처럼 구현하면 된다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;
typedef long long ll;

using namespace std;

ll arr[1000001];
ll seg[2097153];
ll lazy[2097153];

ll init(int L, int R, int sI) {
	if (L == R) return seg[sI] = arr[L];
	return seg[sI] = init(L, (L + R) / 2, sI * 2) + init((L + R) / 2 + 1, R, sI * 2 + 1);
}

void propagate(int L, int R, int sI) {
	seg[sI] += lazy[sI] * (ll)(R - L + 1);
	if (L != R) {
		lazy[sI * 2] += lazy[sI];
		lazy[sI * 2 + 1] += lazy[sI];
	}
	lazy[sI] = 0;
}

ll update(int L, int R, int qL, int qR, ll qVal, int sI) {
	if (lazy[sI]!=0) propagate(L, R, sI);
	if (R < qL || qR < L) return seg[sI];
	if (qL <= L && R <= qR) {
		lazy[sI] += qVal;
		propagate(L, R, sI);
		return seg[sI];
	}
	return seg[sI] = update(L, (L + R) / 2, qL, qR, qVal, sI * 2) + update((L + R) / 2 + 1, R, qL, qR, qVal, sI * 2 + 1);
}
ll query(int L, int R, int qL, int qR, int sI) {
	if (lazy[sI]!=0) propagate(L, R, sI);
	if (R < qL || qR < L) return 0;
	if (qL <= L && R <= qR) return seg[sI];
	return query(L, (L + R) / 2, qL, qR, sI * 2) + query((L + R) / 2 + 1, R, qL, qR, sI * 2 + 1);
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int N, M, K; cin >> N >> M >> K;
	M += K;

	for (int i = 1; i <= N; i++) cin >> arr[i];
	
	init(1, N, 1);

	for (int m = 0; m < M; m++) {
		int a; cin >> a;
		if (a == 1) {
			int x, y; ll z; cin >> x >> y >> z;
			update(1, N, x, y, z, 1);
		}
		else {
			int x, y; cin >> x >> y;
			cout << query(1, N, x, y, 1) << '\n';
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 21237 // C++] Clockwise Fence  (0) 2021.05.05
[BOJ 11000 // C++] 강의실 배정  (0) 2021.05.04
[BOJ 10868 // C++] 최솟값  (0) 2021.05.02
[BOJ 2739 // C++] 구구단  (0) 2021.05.01
[BOJ 10430 // C++] 나머지  (0) 2021.05.01

+ Recent posts