https://www.acmicpc.net/problem/4442
[필자 사고]
이 문제는 inverstion Counting 활용 문제이다.
먼저 문제에서 주어지는 입력값들은 문자로 되어있어서 필자는
map자료구조를 이용하여 해당 값들을 좌표압축을 통해 세그먼트 트리를 손쉽게 작성했다.
그 이후 inverstion 알고리즘을 적용하여 원하는 값들을 출력했다.
[코드 해설]
1. 입력 처리 (Input 함수)
- 목적: 두 개의 문자열 배열을 입력받아 매핑 정보를 생성합니다.
- 첫 번째 입력:
- NN: 배열의 크기.
- arrarr: 첫 번째 문자열 배열로, 순서를 유지한 채 저장합니다.
- 두 번째 입력:
- myMapmyMap: 두 번째 문자열 배열로, 문자열을 정렬된 순서대로 인덱스를 매핑합니다.
- 예: myMap["apple"]=1\text{myMap["apple"]} = 1, myMap["banana"]=2\text{myMap["banana"]} = 2.
- myMapmyMap: 두 번째 문자열 배열로, 문자열을 정렬된 순서대로 인덱스를 매핑합니다.
- 이를 통해, 문자열이 두 배열 간에 어떻게 정렬되었는지 확인할 수 있습니다.
2. 세그먼트 트리 초기화 (InitTree 함수)
- 목적: 세그먼트 트리를 초기화하여 구간 합 계산을 위한 데이터 구조를 준비합니다.
- 4×N4 \times N 크기의 트리를 초기화합니다.
- 모든 값을 0으로 설정하여 초기 상태를 만듭니다.
3. 세그먼트 트리 쿼리 (Query 함수)
- 목적: 특정 범위 [left,right][left, right] 내의 값을 계산합니다.
- 기저 조건:
- 쿼리 범위와 현재 구간이 겹치지 않으면 0을 반환합니다.
- 쿼리 범위가 현재 구간을 완전히 포함하면 해당 노드 값을 반환합니다.
- 재귀 처리:
- 구간을 왼쪽과 오른쪽으로 나누어 각각 쿼리를 수행합니다.
- 두 결과를 합산하여 반환합니다.
4. 세그먼트 트리 갱신 (Update 함수)
- 목적: 특정 위치의 값을 변경하고 세그먼트 트리를 업데이트합니다.
- 기저 조건:
- 변경하려는 인덱스가 현재 구간에 포함되지 않으면 반환합니다.
- 현재 구간이 단일 원소라면 값을 갱신합니다.
- 재귀 처리:
- 구간을 왼쪽과 오른쪽으로 나누어 해당 인덱스가 포함된 자식 노드를 갱신합니다.
- 갱신된 자식 노드 값을 기반으로 부모 노드를 갱신합니다.
5. 역전 수 계산 (Game_Start 함수)
- 목적: 문자열 배열 간 순서 차이를 기반으로 역전 수를 계산합니다.
- 입력값을 읽고 Input 및 InitTree 함수로 초기화합니다.
- 첫 번째 배열의 각 문자열에 대해:
- 해당 문자열이 두 번째 배열에서 매핑된 위치를 가져옵니다 (idxidx).
- 현재 문자열보다 뒤에 있으면서 작은 값의 개수를 세그먼트 트리 쿼리로 계산합니다.
- Query(1,1,N,idx+1,N)\text{Query}(1, 1, N, idx + 1, N)은 idxidx 이후 값들의 합을 구합니다.
- 해당 문자열의 위치를 세그먼트 트리에 추가합니다.
- Update(1,1,N,idx,1)\text{Update}(1, 1, N, idx, 1)은 현재 위치에 1을 추가합니다.
- 모든 문자열에 대해 역전 수를 누적하고 결과를 출력합니다.
[소스 코드]
#include <iostream>
#include <vector>
#define ll long long
using namespace std;
vector<ll> lazy;
vector<ll> tree;
int N, M;
void Propagation(int node, int start, int end) {
if (lazy[node] != 0) {
tree[node] = (end - start + 1) -tree[node];
if (start != end) {
lazy[node * 2] ^= lazy[node];
lazy[node * 2 + 1] ^= lazy[node];
}
lazy[node] = 0;
}
}
void Update(int node, int start, int end, int left, int right) {
Propagation(node, start, end);
if (left <= start && end <= right) {
lazy[node] ^= 1;
Propagation(node, start, end);
return;
}
int mid = (start + end) / 2;
Update(node * 2, start, mid, left, right);
Update(node * 2 + 1, mid + 1, end, left, right);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
int Query(int node, int start, int end, int left, int right) {
Propagation(node, start, end);
if (end < left || right < start) return 0;
if (left <= start && end <= right) {
return tree[node];
}
int mid = (start + end) / 2;
return Query(node * 2, start, mid, left, right) +
Query(node * 2 + 1, mid + 1, end, left, right);
}
void Game_Start() {
cin >> N >> M;
tree.assign(4 * N, 0);
lazy.assign(4 * N, 0);
for (int i = 0; i < M; i++) {
int flag, Si, Ti;
cin >> flag >> Si >> Ti;
if (flag == 0) {
Update(1, 1, N, Si, Ti);
}
else {
cout << Query(1, 1, N, Si, Ti) << '\n';
}
}
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
Game_Start();
return 0;
}
'백준 > 자료구조' 카테고리의 다른 글
백준 8155 c++ "Postering" -PlusUltraCode- (0) | 2025.01.16 |
---|---|
백준 12844 c++ "XOR" -PlusUltraCode- (0) | 2025.01.16 |
백준 14427 c++ "수열과 쿼리 15" -PlusUltraCode- (0) | 2025.01.15 |
백준 4297 c++ "Ultra-QuickSort" -PlusUltraCode- (0) | 2025.01.15 |
백준 1395 c++ "스위치" -PlusUltraCode- (0) | 2025.01.15 |