반응형
리뷰
https://www.acmicpc.net/problem/2517
주어지는 값을 인덱스로 압축하여 세그먼트 트리의 노드로 관리하여 누적합을 구하는 문제
전역 변수
- n : 선수의 수를 저장하기 위한 정수형 변수
- lst : 선수의 평소 실력을 저장하기 위한 정수형 배열
- press : 선수의 실력 정보를 오름차순으로 정렬하기 위한 정수형 배열
- tree : 세그먼트 트리 정보를 저장하기 위한 정수형 배열
함수
1. update
void update(int node, int s, int e, int idx)
세그먼트 트리 정보를 업데이트 하기 위한 함수
- 매개 변수로 노드 정보 node, 탐색 범위 s, e, 업데이트 할 인덱스 idx를 전달 받는다.
- 기저 조건으로 리프 노드에 도달한 경우 현재 노드 값을 1만큼 증가한다.
- 기저 조건에 해당하기 않을 경우 정수형 변수 mid에 탐색 범위의 절반 값을 저장한다.
- idx가 mid보다 작거나 같을 경우 왼쪽 자식 노드로, 클 경우 오른쪽 자식 노드로 재귀를 진행한다.
- 재귀를 빠져 나오며 현재 노드의 값을 좌, 우 자식 노드의 값의 합으로 저장해 준다.
2. query
int query(int node, int s, int e, int L, int R)
현재 선수의 평소 실력보다 크거나 같은 선수의 개수를 구하기 위한 함수
- 매개 변수로 노드 정보 node, 탐색 범위 s, e, 구하고자 하는 범위 L, R을 전달 받는다.
- 첫 번째 기저 조건으로 탐색 범위가 구하고자 하는 범위를 벗어난 경우 0을 리턴해 준다.
- 두 번째 기저 조건으로 탐색 범위가 구하고자 하는 범위와 겹칠 경우 현재 노드의 값을 리턴해 준다.
- 기저 조건에 해당하지 않을 경우 좌, 우 자식 노드로 재귀를 진행하고 각 값을 left, right로 저장해 준다.
- left + right값을 리턴해 준다.
문제풀이
- n값을 입력 받고, n명의 선수의 평소 실력 정보를 lst배열에 입력 받아주고, press배열에도 동일하게 받아준다.
- press배열을 오름차순으로 정렬해 주고, 다시 n번의 for문을 개행해 준다.
- lower_bound 함수를 통해 press에서 현재 선수의 값의 인덱스를 변수 idx에 저장해 준다.
- update 함수를 통해 idx에 값을 증가시켜 준다.
- query 함수를 통해 idx ~ n -1의 누적합을 구해 출력해 준 뒤 줄바꿈을 수행해 준다.
트러블 슈팅
- set을 사용한 문제 풀이를 진행했으나, 시간 초과를 받게 되었다.
- 각 값의 인덱스를 구해 세그먼트 트리의 노드로 활용하여 AC를 받았다.
참고 사항
- 참가한 선수들의 평소 실력은 모두 다르다는 조건이 있으므로 중복을 제거할 필요가 없다.
정답 코드
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 500000;
int n;
int lst[N];
int press[N];
int tree[N * 4];
void update(int node, int s, int e, int idx) {
if (s == e) tree[node]++;
else {
int mid = (s + e) / 2;
if (idx <= mid) update(node * 2, s, mid, idx);
else update(node * 2 + 1, mid + 1, e, idx);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
int query(int node, int s, int e, int L, int R) {
if (R < s || e < L) return 0;
if (L <= s && e <= R) return tree[node];
int mid = (s + e) / 2;
int left = query(node * 2, s, mid, L, R);
int right = query(node * 2 + 1, mid + 1, e, L, R);
return left + right;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> lst[i];
press[i] = lst[i];
}
sort(press, press + n);
for (int i = 0; i < n; ++i) {
int idx = lower_bound(press, press + n, lst[i]) - press;
update(1, 0, n - 1, idx);
cout << query(1, 0, n - 1, idx, n - 1) << "\n";
}
}
728x90
반응형
'알고리즘 공부 > C++' 카테고리의 다른 글
[G1] 백준 1208번 부분수열의 합 2 C++ 이분 탐색, upper_bound, lower_bound (0) | 2025.02.05 |
---|---|
[P4] 백준 1280번 나무 심기 C++ 세그먼트 트리 (0) | 2025.02.04 |
[G2] 백준 4195번 친구 네트워크 C++ 유니온-파인드, 해시맵 (0) | 2025.02.02 |
[G2] 백준 3109번 빵집 C++ 깊이 우선 탐색, 그리디 알고리즘 (0) | 2025.02.01 |
[G3] 백준 9344번 도로 C++ 최소 스패닝 트리, MST (0) | 2025.01.31 |