리뷰
https://www.acmicpc.net/problem/1321
세그먼트 트리를 활용해 군인을 적절한 부대에 배치시키는 문제
전역 변수
- N : 배열의 최대 크기를 저장할 상수 변수
- n : 부대의 개수를 저장할 변수
- lst : 각 부대의 병사 수를 저장할 배열
- tree : 세그먼트 트리 정보를 저장할 배열
함수
1. build
void build(int node, int s, int e) {
if (s == e) tree[node] = lst[s];
else {
int mid = (s + e) / 2;
build(node * 2, s, mid);
build(node * 2 + 1, mid + 1, e);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
누적합 세그먼트 트리를 초기화 하기 위한 함수
2. update
void update(int node, int s, int e, int idx, int val) {
if (s == e) tree[node] += val;
else {
int mid = (s + e) / 2;
if (idx <= mid) update(node * 2, s, mid, idx, val);
else update(node * 2 + 1, mid + 1, e, idx, val);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
세그먼트 트리의 특정 인덱스에 해당하는 노드값을 val만큼 변경하는 함수
3. query
int query(int node, int s, int e, int idx) {
if (s == e) return s;
int mid = (s + e) / 2;
if (idx <= tree[node * 2]) return query(node * 2, s, mid, idx);
return query(node * 2 + 1, mid + 1, e, idx - tree[node * 2]);
}
idx번째 군인이 몇번 부대에 배치될지를 찾는 함수
문제풀이
- n값을 입력 받고, n개 부대의 군인 수를 lst배열에 입력 받아준다.
- build함수를 통해 재귀를 사용하여 세그먼트 트리의 리프노드에 배열의 값을 저장해 준다.
- 재귀를 빠져나오면서 좌, 우 자식 노드의 합을 상위 노드의 값으로 저장해 준다.
- m값을 입력 받고, m개의 쿼리를 수행하여 매 쿼리마다 변수 op, idx에 값을 입력받아 준다.
- op가 1일 경우 변수 val에 추가로 값을 입력 받아주고, update함수를 통해 세그먼트 트리의 idx을 val만큼 변경해준다.
- op가 2일 경우 query함수를 통해 세그먼트 트리의 idx번째 요소가 저장된 노드의 인덱스를 찾아 출력해 준다.
트러블 슈팅
없음
참고 사항
- 쿼리 함수의 idx가 좌측 자식 노드보다 크다면 idx를 좌측 자식 노드의 값만큼 빼주면서 우측 자식 노드로 이동한다.
- idx가 좌측 자식노드보다 작다면 idx를 그대로 좌측 노드로 이동해 준다.
정답 코드
#include<iostream>
using namespace std;
const int N = 500001;
int n, m;
int lst[N];
int tree[N * 4];
void build(int node, int s, int e) {
if (s == e) tree[node] = lst[s];
else {
int mid = (s + e) / 2;
build(node * 2, s, mid);
build(node * 2 + 1, mid + 1, e);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
void update(int node, int s, int e, int idx, int val) {
if (s == e) tree[node] += val;
else {
int mid = (s + e) / 2;
if (idx <= mid) update(node * 2, s, mid, idx, val);
else update(node * 2 + 1, mid + 1, e, idx, val);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
int query(int node, int s, int e, int idx) {
if (s == e) return s;
int mid = (s + e) / 2;
if (idx <= tree[node * 2]) return query(node * 2, s, mid, idx);
return query(node * 2 + 1, mid + 1, e, idx - tree[node * 2]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i) cin >> lst[i];
build(1, 1, n);
cin >> m;
while (m--) {
int op, idx; cin >> op >> idx;
if (op == 1) {
int val; cin >> val;
update(1, 1, n, idx, val);
}
else {
cout << query(1, 1, n, idx) << "\n";
}
}
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[P3] 백준 18227번 성대나라의 물탱크 C++ 세그먼트 트리, 오일러 경로 테크닉 (0) | 2025.03.29 |
---|---|
[P3] 백준 9345번 디지털 비디오 디스크(DVDs) C++ 세그먼트 트리 (1) | 2025.03.28 |
[P5] 백준 10090번 Counting Inversions C++ 세그먼트 트리 (0) | 2025.03.26 |
[G5] 백준 19598번 최소 회의실 개수 C++ 정렬, 멀티셋, 그리디 알고리즘, 이분 탐색 (0) | 2025.03.25 |
[G4] 백준 25417번 고속의 숫자 탐색 C++ 너비 우선 탐색 (0) | 2025.03.24 |