inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

8-D

8-D 북서풍

282

코테

작성한 질문수 14

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

안녕하세요. 강사님 ,

3시간 가량 이 문제를 붙잡아도 도저히 이해가 되지 않네요.. ㅜ - ㅜ

 

아래 코드에서 find_index 함수의 역할이 너무 어려워요.

왜 update(find~+1) 을 하는건지,

find_index 함수는 뭘 출력하는건지 모르겠어요.

v[i].second의 인덱스 출력은 아닌 것 같고,
v[i].second의 개수도 아닌 것 같고...

강의를 3번 듣고, 구글링도 많이 해봤는데..

혼자 계속 고민해봤자 답이 안나올 것 같아요.

 

<아래 코드 출력값>

-10 -10 10 10

-10 => 1

10 => 2

-10 => 1

10 => 2

 

 

ll ret = 0;
    cout << "\n"
         << v[0].second << "  => " << find_index(v[0].second) << "\n";
    update(find_index(v[0].second) + 1, 1);

    for (int i = 1; i < n; i++)
    {
      int idx = find_index(v[i].second) + 1;
      cout << "\n"
           << v[i].second << "  => " << find_index(v[i].second) << "\n";
      ret += 1LL * sum(idx);
      update(idx, 1);
    }

c++ 코딩-테스트

답변 1

0

큰돌

안녕하세요 구재연님 ㅎㅎ

먼저 여기까지 오시느라 수고 많으셨습니다.

 

아래 코드에서 find_index 함수의 역할이 너무 어려워요.

왜 update(find~+1) 을 하는건지,

find_index 함수는 뭘 출력하는건지 모르겠어요.

>>

이코드 말씀이시죠?

        for(int i = 0; i < n; i++){
            cin >> x >> y;
            a.push_back({x, y * -1});
            _y.push_back(y * -1);
        }
        sort(a.begin(), a.end());
        sort(_y.begin(), _y.end());
        ll ret = 0;
        update(find_index(_y, a[0].second) + 1, 1);

_y는 y좌표들이 반대로 담깁니다.

_y = -1 * y좌표리스트

a[0].second가 의미하는 것은 y * -1가 들어간 값입니다.

해당 값을 찾아서 인덱스를 반환합니다.

int find_index(const vector<int> & _y, int value){
    int lo = 0, hi = _y.size() - 1;
    while(lo <= hi){
        int mid = (lo + hi) / 2;
        if(_y[mid] == value) return mid;
        if(_y[mid] < value) lo = mid + 1;
        else hi = mid - 1;
    }
}

이미 sort가 되어있기 때문에 이분탐색을 쓸 수가 있습니다.

예를 들어

-1, -2, -3, -4가 들어가있고 -3을 찾는다면 2라는 인덱스를 반환합니다.

자 좀 더 쉬운 예제로 들어볼게요.


1
3
5 1 
4 2
3 3

이거를 기반으로.

#include <bits/stdc++.h>
#define max_n 75004
typedef long long ll;
using namespace std;
int n, x, y, t;
vector<int> tree, _y;
vector<pair<int, int>> a;

int sum (int idx){
    int ret = 0;
    while(idx > 0){
        ret += tree[idx];
        idx -= (idx & -idx);
    }
    return ret;
}
void update(int pos, int value){
    int idx = pos;
    while(idx <= n){
        tree[idx] += value;
        idx += (idx & -idx);
    }
    return;
}
int find_index(const vector<int> & _y, int value){
    int lo = 0, hi = _y.size() - 1;
    while(lo <= hi){
        int mid = (lo + hi) / 2;
        if(_y[mid] == value) return mid;
        if(_y[mid] < value) lo = mid + 1;
        else hi = mid - 1;
    }
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
    cout.tie(NULL);
    cin >>t;
    while(t--){
        cin >> n;
        a.clear(); _y.clear();
        tree.clear();
        tree.resize(n + 1);
        for(int i = 0; i < n; i++){
            cin >> x >> y;
            a.push_back({x, y * -1});
            _y.push_back(y * -1);
        }
        sort(a.begin(), a.end());
        sort(_y.begin(), _y.end());
        ll ret = 0; 
        update(find_index(_y, a[0].second) + 1, 1);
        for(int i = 1; i < n; i++){
            cout << "index\n";
            cout << a[i].second << " : " << find_index(_y, a[i].second) << "\n";
            int idx = find_index(_y, a[i].second) + 1;
            ret += 1LL * sum(idx);update(idx, 1);
        }
        cout << ret << "\n";
    }
	return 0;
}

디버깅 코드는 앞의 코드와 같습니다.

첫번째 인덱스를 제외하고 출력하는거라 이렇게 출력이 될 겁니다.

index

-2 : 1

index

-1 : 2

 

이 의미는.

-2를 _y 안에서 찾아줘.

가 되죠.

_y는 -3, -2, -1이 들어가있겠죠?

이 안에서 -2는 1을. -1는 2를 반환하게 됩니다.

 

 

그 이후 해당 인덱스 + 1에 해당 하는 펜윅트리를 업데이트합니다.

이 때 + 1을 하는 이유는 인덱스는 0 ~ n - 1이렇게 반환될텐데

펜윅트리는 1부터 시작하므로 + 1을 해줍니다.

업데이트를 왜하냐?

>>

펜윅트리를 통해 우리는 어떤 정점에서 그 이전에 몇개의 정점이 얼마나 있는지를 쉽게 파악할 수 있습니다.

예를 들어

1 1 1 1 3이라고 했을 때 3 뒤에는 1이 4개가 있죠?

이를 빨리 파악할 수 있게 하는 자료구조가 펜윅트리입니다.

1이라는 값에 +1을 함으로써 결국 1이라는 값은 4만큼의 크기를 가지고 3에서 그 밑에 있는 수를 끄집어낸다 했을 때

sum이라는 함수로 4개를 끄집어낼 수 있는 것이죠.

다시 예를 들면

1 1 1 1 2 2 3 이렇게 되어있을 떄

1 : 4, 2 : 2 이런식으로 되어서

sum()을 기반으로

3밑에 6개가 있네 를 쉽게 뽑아낼 수 있게 되는 것입니다.



또 질문 있으시면 언제든지 질문 부탁드립니다.

좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)

감사합니다.

강사 큰돌 올림.


4 - A

0

9

1

코딩살구클럽 입장이 안됩니다

0

49

2

4-F 경우의 수 질문입니다.

0

30

2

코딩살구클럽 가입이 안됩니다.

0

63

2

살구 클럽에 대한 질문있습ㄴ디ㅏ

0

53

1

교안 158페이지 문의드립니다

0

44

2

코딩살구클럽 관련 건의사항

0

105

1

코살에 19942 다이어트 문제에 N의 범위가 빠져있슴니다

0

44

1

진행 방법 질문드립니다!

0

78

2

2-I) 왜 이 문제가 그래프이론 카테고리에 있는지 잘 모르겠습니다.

0

63

2

2주차 개념#12 트리 순회

0

32

2

백준사이트가 종료된다고 합니다.

0

307

2

백준 서비스 종료

9

943

1

sk 하이닉스 코테 대비

0

382

2

3-G 최댓값 질문

0

53

1

모듈러 연산 값이 10이 아닌 경우도 있지 않나요?

0

84

2

3-I 코드 질문드립니다.

0

63

2

3-N 질문 있습니다.

0

68

2

학습방법

0

105

2

4-H 질문 있습니다 (코드 리뷰)

0

68

2

코딩테스트 어디까지 준비해야 하는지 질문이 있습니다.

0

179

2

2-O 반례가 무엇일지 어떤 부분이 틀렸는지 잘 모르겠습니다.

0

71

2

2주차 개념 #4-2. 인접행렬 질문있습니다.

0

65

2

1-A 문제풀이 후 궁금한 점이 생겨서 질문드립니다.

0

53

2