Algorithm/백준
[C++] 16975번: 수열과 쿼리 21(Lazy Propagation)
hanbikan
2021. 11. 22. 23:40
https://www.acmicpc.net/problem/16975
16975번: 수열과 쿼리 21
길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i j k: Ai, Ai+1, ..., Aj에 k를 더한다. 2 x: Ax 를 출력한다.
www.acmicpc.net
- 배경
Segment Tree의 Lazy Propagation을 안다는 전제로 글을 작성하였으니, 해당 개념에 대해서는 다음 링크를 참조하자.
[Python] Lazy Propagation (백준 10999번: 구간 합 구하기 2)
https://www.acmicpc.net/problem/10999 10999번: 구간 합 구하기 2 첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고,..
rccode.tistory.com
- 풀이
일반적인 세그먼트 트리로는 시간복잡도에 걸리므로, Lazy Propagation을 통한 효율적인 풀이를 사용하였다.
느리게 갱신되는 세그먼트 트리의 기본 형태에, query문을 한 개 원소의 영역에 대해서 수행해주기만 하면 된다.
#include <iostream>
using namespace std;
long long A[100001];
long long segTree[400004];
long long lazy[400004];
long long initializeSegTree(int index, int start, int end) {
if (start == end) segTree[index] = A[start];
else {
int mid = (start + end) / 2;
segTree[index] = initializeSegTree(index * 2, start, mid) +
initializeSegTree(index*2+1, mid+1, end);
}
return segTree[index];
}
void propagateSegTree(int index, int start, int end) {
if (lazy[index] != 0) {
if (start != end) {
lazy[index * 2] += lazy[index];
lazy[index * 2 + 1] += lazy[index];
}
segTree[index] += (end - start + 1) * lazy[index];
lazy[index] = 0;
}
}
void updateSegTree(int index, int start, int end, int left, int right, int toAdded) {
propagateSegTree(index, start, end);
if (right < start || end < left) return;
if (left <= start && end <= right) {
lazy[index] += toAdded;
propagateSegTree(index, start, end);
return;
}
int mid = (start + end) / 2;
updateSegTree(index * 2, start, mid, left, right, toAdded);
updateSegTree(index * 2+1, mid+1, end, left, right, toAdded);
segTree[index] = segTree[index * 2] + segTree[index * 2 + 1];
}
long long querySegTree(int index, int start, int end, int left, int right) {
propagateSegTree(index, start, end);
if (right < start || end < left) return 0;
if (left <= start && end <= right) return segTree[index];
int mid = (start + end) / 2;
return querySegTree(index * 2, start, mid, left, right) +
querySegTree(index * 2 + 1, mid + 1, end, left, right);
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int i;
int N;
cin >> N;
for (i = 1; i < N+1; i++) cin >> A[i];
initializeSegTree(1, 1, N);
int M;
cin >> M;
for (i = 0; i < M; i++) {
int op;
cin >> op;
if (op == 1) {
int a, b, k;
cin >> a >> b >> k;
updateSegTree(1, 1, N, a, b, k);
}
else {
int x;
cin >> x;
cout << querySegTree(1, 1, N, x, x) << "\n";
}
}
}