리뷰
https://www.acmicpc.net/problem/1777
[P4] 백준 1849번 순열 C++ 세그먼트 트리
리뷰 https://www.acmicpc.net/problem/1849구간 합 세그먼트 트리를 통해 답을 도출하는 문제 전역 변수N : 배열의 최대 크기를 저장할 상수 변수n : 수열 원소의 개수를 저장할 변수s : 매 원소를 입력
zzzz955.tistory.com
위 문제의 반대 버전
전역 변수
- N : 순열의 최대 크기를 저장할 상수 변수
- n : 순열의 크기를 저장할 변수
- s : 각 인버전 시퀀스 값을 저장할 변수
- lst : 순열의 인버전 시퀀스를 저장할 배열
- ans : 순열의 요소를 저장할 배열
- 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) {
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];
}
}
세그먼트 트리 정보를 업데이트 하기 위한 함수
3. query
int query(int node, int s, int e, int val) {
if (s == e) return s;
int mid = (s + e) / 2;
if (val < tree[node * 2 + 1]) return query(node * 2 + 1, mid + 1, e, val);
return query(node * 2, s, mid, val - tree[node * 2 + 1]);
}
인버전 시퀀스 값을 기준으로 순열의 몇번째 요소에 값이 할당되어야 하는지를 구하기 위한 함수
문제풀이
- n값을 입력 받고, lst배열의 1~n번째 인덱스를 모두 1로 초기화 해준다.
- build함수를 통해 누적합 세그먼트 트리를 초기화 해준다.
- lst배열의 1~n번째 인덱스에 인버전 시퀀스 값을 입력 받아준다.
- n부터 1번인덱스 까지 역순으로 순회하며 lst배열의 현재 인덱스 값을 변수 s에 저장해 준다.
- 변수 idx에 쿼리 함수에 s를 매개변수로 전달하여 리턴받은 값을 저장해 준다.
- ans의 idx에 i를 저장해 주고, update함수에 idx를 전달하여 세그먼트 트리 업데이트를 진행해 준다.
- 모든 쿼리가 수행된 후 ans의 배열의 1~n까지 저장된 값을 공백을 기준으로 출력해 준다.
트러블 슈팅
없음
참고 사항
- 규칙성이 시퀀스를 뒤에서부터 탐색할때 발생한다는 것을 깨달으면 순열문제와 유사하다는 것을 알 수 있다.
정답 코드
#include<iostream>
using namespace std;
const int N = 1e5 + 1;
int n, s;
int lst[N];
int ans[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) {
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 val) {
if (s == e) return s;
int mid = (s + e) / 2;
if (val < tree[node * 2 + 1]) return query(node * 2 + 1, mid + 1, e, val);
return query(node * 2, s, mid, val - tree[node * 2 + 1]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i) lst[i] = 1;
build(1, 1, n);
for (int i = 1; i <= n; ++i) cin >> lst[i];
for (int i = n; i >= 1; --i) {
s = lst[i];
int idx = query(1, 1, n, s);
//cout << "result of query : " << idx << "\n";
ans[idx] = i;
update(1, 1, n, idx);
}
for (int i = 1; i <= n; ++i) cout << ans[i] << " ";
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[P3] 백준 12895번 화려한 마을 C++ 세그먼트 트리, 느리게 갱신되는 세그먼트 트리, 비트마스킹 (1) | 2025.04.03 |
---|---|
[P4] 백준 1849번 순열 C++ 세그먼트 트리 (0) | 2025.04.01 |
[P4] 백준 11962번 Counting Haybales C++ 세그먼트 트리, 느리게 갱신되는 세그먼트 트리 (0) | 2025.03.31 |
[P4] 백준 2934번 LRH 식물 C++ 세그먼트 트리, 느리게 갱신되는 세그먼트 트리 (0) | 2025.03.30 |
[P3] 백준 18227번 성대나라의 물탱크 C++ 세그먼트 트리, 오일러 경로 테크닉 (0) | 2025.03.29 |