※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 10999번 문제인 구간 합 구하기 2이다.
문제는 아래 링크를 확인하자.
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 |