10090번: Counting Inversions
A permutation of integers from 1 to n is a sequence a1, a2, ..., an, such that each integer from 1 to n is appeared in the sequence exactly once. Two integers in а permutation form an inversion, when the bigger one is before the smaller one. As an example
www.acmicpc.net
분할 정복
1. 문제해결 아이디어
임의의 수열에서 자신보다 뒤에 있는데 자신보다 작은 수의 개수의 총 합을 구하는 문제이다
N^2로 풀면 너무 쉽겠지만 N <= 1000000이므로 불가능하다.
이전에 버블 소트_1517 문제를 푼 경험이 있어서 병합 정렬 과정을 직접 손으로 그려가며 계산해보니까
구현에 대한 감이 바로왔다
*병합정렬 과정에서 arr[lo]와 arr[hi]를 비교했을 때 arr[hi]가 더 작다는 말은
arr[lo~mid]까지의 모든 원소가 arr[hi]보다 크다는 말이다
Ex) 4 7 / 1 2 3 처럼 나누어져 있을 때
1. arr[lo] = 4이고 arr[hi] = 1이다
arr[hi]가 더 작으므로 lo(0)~mid(1)까지의 거리(mid-lo+1) (2) 만큼 Inv에 더해준다
그리고 hi++를 해서 오른쪽 배열의 두 번째 원소로 index를 옮겨준다
2. arr[lo] = 4, arr[hi] = 2 이다
위와 동일하게 Inv에 2를 더해주고 hi++해준다
3... 반대의 경우는 Inv에 더해주는 작업을 안해주면 됨
그리고 while문을 돌면서 temparr에 저장해 놓았던 정렬된 배열을 가지고
for문에서 arr배열에 업데이트해주는 작업을 하면 끝
2. 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <iostream> #include <vector>
using namespace std;
vector<int> arr, temparr;
int N;
long long Inv = 0;
void counting_inversions(int st, int ed){
if(st == ed) return;
int mid = (st + ed)/2;
counting_inversions(st, mid);
counting_inversions(mid+1, ed);
int lo = st;
int hi = mid+1;
long long temp_Inv = 0;
int idx = 0;
while(lo <= mid || hi <= ed){
if(lo <= mid && (hi > ed || arr[lo] < arr[hi])){
temparr[idx++] = arr[lo++];
}
else{
temparr[idx++] = arr[hi++];
temp_Inv += (mid - lo + 1);
}
}
for(int i = st; i <= ed; i++){
arr[i] = temparr[i - st];
}
Inv += temp_Inv;
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
cin >> N;
arr.resize(N+1);
temparr.resize(N+1);
for(int i = 0; i < N; i++){
cin >> arr[i];
}
counting_inversions(0, N-1);
cout << Inv;
return 0;
}
|
cs |
'Algorithm > BOJ' 카테고리의 다른 글
[백준 3109] 빵집 C++ (0) | 2021.04.22 |
---|---|
[백준 12015] 가장 긴 증가하는 부분 수열2 C++ (1) | 2021.04.21 |
[백준 1111] IQ Test C++ (0) | 2021.04.19 |
[백준 14501] 퇴사 C++ (0) | 2021.03.22 |
[백준 2798] 블랙잭 C++ (0) | 2021.03.22 |