[트리] [시도x] MEASURETIME

2021. 2. 8. 19:44알고리즘/알고리즘 문제 [hard]

1. 펜윅트리를 이용한 풀이

 

처음에 이 문제를 봤을때 

 

펜윅트리를 어떻게 써야할 지 감을 못잡았다.

 

책에서는 수열의 입력값으로 이루어진 트리를 만들고

 

해당 입력값이 오게되면 그것을 포함하는 구간을 전부 +1을 해줘서

 

루트에 현재 수열의 길이를 저장하게 되고

 

입력값 까지의 부분합을 구하게 되면 

 

현재 수열중에서 입력값보다 작은 것들의 개수를 알 수 있다.

 

이를 통해 자신보다 큰 원소의 개수를 알 수 있고, 앞으로 몇칸 이동 시켜야하는지 파악할 수 있다. 

 

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
#include <iostream>
#include <vector>
 
using namespace std;
 
struct FenwickTree {
    vector<int> tree;
    FenwickTree(int n) : tree(n+10) {}
    int sum(int pos) {
        ++pos;
        int ret = 0;
        while(pos>0) {
            ret += tree[pos];
            pos&=(pos-1);
        }
        return ret;
    }
    void add(int pos, int val) {
        ++pos;
        while(pos < tree.size()) {
            tree[pos] += val;
            pos += (pos & -pos);
        }
    }
};
 
 
 
int C, N;
vector<int> A;
 
long long totalMove() {
    long long ret = 0;
    FenwickTree tree(1000000);
    for(int i = 0; i < A.size(); i++) {
        ret += tree.sum(1000000-1- tree.sum(A[i]);
        tree.add(A[i], 1);
    }
    return ret;
}
int main() {
    cin>>C;
    while(C--) {
        cin>>N;
        A.clear();
        A.resize(N);
        while(N--) {
            int tmp;
            cin>>tmp;
            A.push_back(tmp);
        }
        cout<<totalMove()<<"\n";
    }
}
cs

 

2. 이진 검색 트리를 이용한 방법

 

이진 검색또한 균형 잡힌 트리를 이용하여 

 

입력들을 순서대로 정렬 시킨 뒤 

 

주어진 입력 값 보다 작은 원소의 개수를 구해

 

답을 구한다

 

이는 균형 잡힌 트리를 구현해야 하므로 펜윜트리보다 구현하기 까다롭다.

 

3. merge sort를 이용한 방법

 

merge sort에서 값을 이동시킬때마다 카운트하는 방법이다.

 

병합 정렬에서는 i < j 인 i,j에서 A[j] < A[i] 일때만 값이 움직다.

 

따라서 분할하고 정복하는 과정에서

 

왼쪽 부분 배열A 와 오른쪽 부분 배열 B를 각각 처음부터 비교해나가면서

 

A[a] > B[b] 인 a 와 b가 될때 a의 오른쪽 끝까지 전부 B[b] 보다 큰 값이므로

 

이들의 개수를 전부 더한 값이 

 

문제에서 원하는 답이된다.

 

 

 

 

 

 

-알고리즘 문제해결전략 760p