[백준] [C++] 3015번 오아시스 재결합 (stack)

2021. 7. 14. 15:16알고리즘/백준

 

1. 문제

3015번: 오아시스 재결합 (acmicpc.net)

 

3015번: 오아시스 재결합

첫째 줄에 줄에서 기다리고 있는 사람의 수 N이 주어진다. (1 ≤ N ≤ 500,000) 둘째 줄부터 N개의 줄에는 각 사람의 키가 나노미터 단위로 주어진다. 모든 사람의 키는 231 나노미터 보다 작다. 사람

www.acmicpc.net

 

2. 풀이

이 문제의 핵심은 같은 키를 가진 사람들이다.

 

문제의 정의에의해

같은 키를 가진 사람들이 연속적으로 줄을 서고 있을때

서로를 볼 수 있기 때문이다.

따라서 pair를 사용하여 같은 키인 사람의 수를 따로 저장하여 처리해야한다.

 

알고리즘은 다음과 같다

1) 앞에서부터 스택에 담는다

2) 스택에 담기전 스택의 top 보다 큰값이면 스택의 top이 더 큰값이 올때까지 pop해준다.

   pop의 의미는 현재 사람과, top의 사람이 쌍을 이룸을 의미한다.

3) 스택이 비어있지않으면, top과 현재 인덱스가 쌍을 이룬다는것을 의미한다.

    만약 top과 현재 인덱스의 키가 같으면 이는 top을 업데이트 시켜줘야함을 의미하며,

    현재의 인덱스는 이전의 연속적인 사람의 수들만큼 쌍이 생긴다는것을 의미한다.

 

 

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
68
69
70
71
72
#include <bits/stdc++.h>
 
using namespace std;
int N;
vector<long long> h;
 
void solve() {
    long long answer = 0;
    vector<pair<long longint>> s;
    for(int i = 0; i < N; i++) {
        int count = 1;
        while(!s.empty() && s.back().first < h[i]) {
            //h[i]와의 쌍
            answer += s.back().second;
            s.pop_back();
        }
        //s.back()과의 쌍
        if(!s.empty() && s.back().first == h[i]) {
            answer += s.back().second;
            count = s.back().second+1;
            s.pop_back();
        }
        if(!s.empty()) {
            answer++;
        }
        s.push_back({h[i], count});
    }
 
    cout<<answer;
}
void solve2() {
    long long answer = 0;
    vector<int> s;
    h.push_back(INT64_MAX);
    for(int i = 0; i < N+1; i++) {
        long long back = h[i], count = 0;
        if(i == N) {
            answer -= s.size();
        }
        while(!s.empty() && h[s.back()] < h[i]) {
            // 같은것끼리 쌍을 이루는것
            if(back == h[s.back()]) {
                count++;
                answer += count;
            }
            else {
                count = 0;
            }
            back = h[s.back()];
            //h[i] 와 쌍을 이루는것
            answer++;
            s.pop_back();
        }
        if(!s.empty() && h[s[0]] != h[i]) {
            //s[0] 와 쌍을 이루는것
            answer++;
        }
        s.push_back(i);
    }
 
    cout<<answer;
}
int main() {
    cin>>N;
    h = vector<long long>(N);
    for(int i = 0; i < N; i++) {
        cin>>h[i];
    }
    solve();
   // cout<<"\n";
   // solve2();
}
cs