PS/BOJ

[백준 BOJ][세그먼트 트리] 2336 굉장한 학생

Jubil 2018. 12. 1. 22:24
반응형

2336_굉장한 학생

링크

https://www.acmicpc.net/problem/2336

 

풀이


 

시험을 3번 치룹니다. 어떤 학생보다 대단한 학생이 없어야 그 학생이 굉장한 학생입니다.

 

학생은 1~N 순서대로 번호가 부여되기 때문에, 첫 번째 등수를 기준으로 정렬을 합니다.

그럼 정렬을 한 상태에서 i번째 학생이 굉장하려면 1~i-1번째 학생 중에 대단한 학생을 찾으면 됩니다. 왜냐하면 i+1~N번째 학생은 이미 첫 번째 시험에서 밀렸기 때문이죠.

 

그럼 2번째 등수와 3번째 등수가 남았는데, 2번째 등수를 세그먼트 트리의 인덱스로 놓고 3번째 등수를 값으로 저장하게 합니다.

 

그 다음 1 ~ 2번째 등수 - 1에서 값의 최솟값을 뽑으면 나보다 2번째 등수가 높은 사람들 중에 3번째 등수의 최솟값이 나옵니다. 만약 이 등수보다 내 등수가 안 나왔다? 그러면 i번째 학생보다 1,2,3번째 시험 모두 다 잘 본 학생이 존재한다는 말이겠죠?

 

이렇게 count를 잘 해서 출력을 하면 됩니다.

 

코드

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

56

57

58

59

60

61

62

63

64

65

66

67

//2336_굉장한 학생

#include <cstdio>

#include <algorithm>

#include <vector>

#define MAX 500001

using namespace std;

 

int n, ans, tmp;

int a[MAX], b[MAX], c[MAX];

int tree[MAX * 4];

vector<pair<intpair<intint>>> v;

 

int init(int node, int start, int end) {

    if (start == end)

        return tree[node] = 1e9;

    else

        return tree[node] = max(init(node * 2, start, (start + end/ 2), init(node * 2 + 1, (start + end/ 2 + 1end));

}

 

void update(int node, int start, int endint index, int val) {

    if (index < start || index > endreturn;

    if (start == end) {

        tree[node] = val;

        while (node >= 1) {

            node /= 2;

            tree[node] = min(tree[node * 2], tree[node * 2 + 1]);

        }

        return;

    }

    else {

        update(node * 2, start, (start + end/ 2, index, val);

        update(node * 2 + 1, (start + end/ 2 + 1end, index, val);

    }

}

 

int findMin(int node, int start, int endint left, int right) {

    if (left > end || right < start) return 1e9;

    else if (left <= start && right >= endreturn tree[node];

    return min(findMin(node * 2, start, (start + end/ 2, left, right), findMin(node * 2 + 1, (start + end/ 2 + 1end, left, right));

}

 

int main() {

    scanf("%d"&n);

    for (int i = 0; i < MAX * 4++i) tree[i] = 1e9;

 

    v.push_back(make_pair(0make_pair(00)));

    for (int i = 1; i <= n; ++i) scanf("%d"&tmp), a[tmp] = i;

    for (int i = 1; i <= n; ++i) scanf("%d"&tmp), b[tmp] = i;

    for (int i = 1; i <= n; ++i) scanf("%d"&tmp), c[tmp] = i;

    for (int i = 1; i <= n; ++i) v.push_back(make_pair(a[i], make_pair(b[i], c[i])));

 

    sort(v.begin(), v.end());

 

    //for (int i = 1; i <= n; ++i) printf("%d %d %d\n", v[i].first, v[i].second.first, v[i].second.second);

 

    //2번째 값을 인덱스로, 3번째 값을 갖는 세그먼트 트리를 구성

    //i번째가 굉장한 학생이려면 세그트리에서 (1 ~ i  번째 -1)까지의 최솟값이 i 3번째 값보다 커야함

 

    for (int i = 1; i <= n; ++i) {

        if (findMin(11, n, 1, v[i].second.first - 1> v[i].second.second) ans++;

        update(11, n, v[i].second.first, v[i].second.second);

    }

 

    printf("%d\n", ans);

 

    return 0;

}

Colored by Color Scripter

cs

 



반응형

'PS > BOJ' 카테고리의 다른 글

[백준 BOJ] 1476 날짜 계산  (0) 2019.08.10
[백준 BOJ] 5532 방학 숙제  (0) 2018.12.02
[백준 BOJ] 16435 스네이크 버드  (0) 2018.11.29
[백준 BOJ] 16431 베시와 데이지  (0) 2018.11.28
[백준 BOJ][DP] 16507 어두운 건 무서워  (0) 2018.11.27