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
Segment Tree 공부하기
겉보기에는 구간합을 구하는 간단한 문제처럼보이지만
Segment Tree 자료구조를 이해해야 풀 수 있는 문제입니다.
하단 링크에 설명이 잘 되어 있습니다.
https://www.acmicpc.net/blog/view/9
세그먼트 트리 (Segment Tree)
문제 배열 A가 있고, 여기서 다음과 같은 두 연산을 수행해야하는 문제를 생각해봅시다. 구간 l, r (l ≤ r)이 주어졌을 때, A[l] + A[l+1] + ... + A[r-1] + A[r]을 구해서 출력하기 i번째 수를 v로 바꾸기. A[i
www.acmicpc.net
하단의 영상은 제가 올린 건 아니고
유튜브에 개발자영맨님이 만든 Segment Tree 강의인데
설명이 잘 되어 있어서 같이 올려봅니다.
https://www.youtube.com/watch?v=075fcq7oCC8
https://www.youtube.com/watch?v=ahFB9eCnI6c
문제풀이코드 C++
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int n, m, k;
long long arr[1000003];
struct SegmentTree {
int N;
vector<long long> tree;
long long merge(long long left, long long right) {
return left + right;
}
long long buildRec(int node, int nodeLeft, int nodeRight) {
if (nodeLeft == nodeRight) {
return tree[node] = arr[nodeLeft];
}
int mid = (nodeLeft + nodeRight) / 2;
long long LeftVal = buildRec(2 * node, nodeLeft, mid);
long long RightVal = buildRec(2 * node + 1, mid + 1, nodeRight);
return tree[node] = merge(LeftVal, RightVal);
}
void init(int Size) {
N = Size;
tree.resize(N * 4);
buildRec(1, 0, N - 1);
}
long long queryRec(int left, int right, int node, int nodeLeft, int nodeRight) {
// 노드 구간이 구하는 구간 밖일 경우 0 리턴
if (nodeRight < left || right < nodeLeft) {
return 0;
}
if (left <= nodeLeft && nodeRight <= right) {
return tree[node];
}
int mid = (nodeLeft + nodeRight) / 2;
long long leftVal = queryRec(left, right, 2 * node, nodeLeft, mid);
long long rightVal = queryRec(left, right, 2 * node + 1, mid + 1, nodeRight);
return merge(leftVal, rightVal);
}
long long query(int left, int right) {
return queryRec(left, right, 1, 0, N - 1);
}
long long updateRec(int index, long long newValue, int node, int nodeLeft, int nodeRight) {
if (nodeRight < index || index < nodeLeft) return tree[node];
if (nodeLeft == nodeRight) {
return tree[node] = newValue;
}
int mid = (nodeLeft + nodeRight) / 2;
long long leftVal = updateRec(index, newValue, 2 * node, nodeLeft, mid);
long long rightVal = updateRec(index, newValue, 2 * node + 1, mid + 1, nodeRight);
return tree[node] = merge(leftVal, rightVal);
}
void update(int index, long long newValue) {
updateRec(index, newValue, 1, 0, N - 1);
}
};
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> k;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
SegmentTree st;
st.init(n);
for (int i = n + 2; i <= n + m + k + 1; i++) {
int a, b;
long long c;
cin >> a >> b >> c;
if (a == 2) {
cout << st.query(b - 1, c - 1) << '\n';
}
else {
st.update(b - 1, c);
}
}
return 0;
}

백준 2042 반례
5 1 1
1
2
3
4
5
1 2 300000000000
2 2 5
answer: 300000000012
a, b, c 를 입력 받을 때 c를 long long 형으로 입력받아야합니다.
업데이트를 해주는 과정에서도 long long 자료형을 유지해 업데이트를 진행해야합니다.
'Algorithm > problem' 카테고리의 다른 글
백준 1753번 : 최단 경로 - 다익스트라 C++ 코드 (0) | 2022.02.13 |
---|---|
백준 3111번 : 검열 - deque 활용 코드 C++ (0) | 2022.02.12 |
백준 9935번 : 문자열 폭발 - C++ 스택 직접 구현 (0) | 2022.02.10 |
백준 2812번 : 크게 만들기 (0) | 2022.02.10 |
백준 11559번 : Puyo Puyo C++ 문제풀이코드 (0) | 2022.02.10 |