이 영역을 누르면 첫 페이지로 이동
자라자 블로그의 첫 페이지로 이동

자라자

페이지 맨 위로 올라가기

자라자

개발자를 준비하는 자라자의 블로그입니다.

백준 3015 오아시스 재결합 c++

  • 2022.01.25 00:13
  • PS/BOJ

백준로고

[문제 링크]

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

[입출력 예]

입력 출력
7
2
3
1
2
2
5
1
10

[1차시도 - 실패]

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second

ll a[500000];

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    ll answer=0;

    int n;
    cin>>n;
    stack <pair<ll,int>> s;
    pair<ll,int>max_pair ={(ll)INT_MAX +1,n};
    s.push(max_pair);

    //배열에 대입.
    for (int i=0; i<n; i++){
        cin>>a[i];
    }

    //반복문으로 오큰수처럼 풀이
    for (int i=n-1; i>=0; i--){

        // stack의 탑보다 큰 경우 -> top보다 요소가 작을때까지  top 빼기.
        if (s.top().X<a[i]){

            while(s.top().X < a[i]){
                s.pop();
                answer+=1;
            }
                if (s.top().Y!=n)answer+=1;
                s.push({a[i],i});

        }
        // stack의 탑보다 작은 경우
        else if (s.top().X>a[i]){

            s.push({a[i],i});
            if (i != n-1)answer+=1;
        }
        else {
          int tmpIdx;
          while(s.top().X==a[i]){
            tmpIdx=s.top().Y;
            s.pop();
          }
          answer+=tmpIdx-i;
          if (s.top().Y!=n) answer+=1;
          s.push({a[i],tmpIdx});
        }
    }

    cout<<answer;
    return 0;
}

// 이런 풀이로 풀 수가 없다.
// 이 풀이는 인덱스만 가지고 푸는 건데, 그렇게 푼다는 건 스택 안에 전조증가 수열로 남긴다는 것이다.
// 근데 그렇게 풀면 똑같은 키가 여러 번 나올 때 하나하나 다 세주기가 어렵게 된다.
// 그래서 몇번 반복되는지를 반드시 변수로 세서 넣어줘야 한다...

[소스코드]

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second

int main(void) {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  stack<pair<int, int>> S;
  long long ans = 0;
  while (n--) {
    int h;
    cin >> h;
    int cnt = 1;
    while (!S.empty() && S.top().X <= h) {
      ans += S.top().Y;
      if (S.top().X == h) cnt += S.top().Y;
      S.pop();
    }
    if (!S.empty()) ans++;
    S.push({h, cnt});
  }
  cout << ans;
}

// [문제 해설]
// 1. 스택에는 이전까지의 키가 내림차순으로 쌓이게 된다.
// 2. 스택에 아무것도 없는 상황에서 새로운 데이터를 만난 경우, 스택에 데이터와 기본카운트 1을 넣는다.
// 3. 새롭게 만난 데이터가 스택의 top보다 크거나 같은 경우, stack의 top의 cnt를 더한다.
// 4. cnt는 해당 키를 가진 인물이 스택 속에 연속적으로 몇명이나 있는가.. 를 의미하는 것과 같다.
// 5. 새롭게 만난 데이터가 스택의 top보다 크다면, 그 데이터보다 큰 top이 나올 때까지 pop을 수행한다.
// 6. 그런데 이때, 새롭게 만난 데이터(h)와 stack의 탑이 같다면, 카운트를 올려줘서 새로운 데이터에 해당하는 값이 연속몇번인지 센다.
// 7. 뽑다 보면 경우의 수는 2가지로 나뉘는데, 끝가지 스택을 비워버리거나, 스택의 어떤 값에 막히는 경우일 것이다.
// 8. 만약 어떤 값에 막히는 경우라면(not empty) 그 사람을 볼 수 있는 상황이므로 ans에 하나 값을 더한다.
// 9. 끝가지 다 뽑았으면 끝까지 다 본 것이므로 ans를 조작하지 않는다.
// 10. 현재 해당하는 h값을 연속하는 회수 cnt와 함께 스택에 넣는다.

[출처]

https://github.com/encrypted-def/basic-algo-lecture/blob/master/0x05/solutions/3015.cpp

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

백준 10845 큐,큐2 c++  (0) 2022.02.01
백준 6549 히스토그램에서 가장 큰 직사각형 풀이 c++  (0) 2022.01.25
백준 17298 오큰수 c++  (0) 2022.01.13
백준 6918 옥상 정원 꾸미기 c++  (0) 2022.01.13
백준 1874 스택수열 c++  (0) 2022.01.08

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • 백준 10845 큐,큐2 c++

    백준 10845 큐,큐2 c++

    2022.02.01
  • 백준 6549 히스토그램에서 가장 큰 직사각형 풀이 c++

    백준 6549 히스토그램에서 가장 큰 직사각형 풀이 c++

    2022.01.25
  • 백준 17298 오큰수 c++

    백준 17298 오큰수 c++

    2022.01.13
  • 백준 6918 옥상 정원 꾸미기 c++

    백준 6918 옥상 정원 꾸미기 c++

    2022.01.13
다른 글 더 둘러보기

정보

자라자 블로그의 첫 페이지로 이동

자라자

  • 자라자의 첫 페이지로 이동

검색

메뉴

  • 🏠 HOME
  • 💡 ABOUT
  • 💻 GITHUB

카테고리

  • 분류 전체보기 (91)
    • Tech Note (3)
    • Dev Log (11)
    • Study Log (11)
    • Settings (3)
    • PS (53)
      • Programmers (21)
      • BOJ (32)
    • Diary (10)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • ㅣ
  • 리액트
  • 공식문서읽기

나의 외부 링크

정보

자라자의 자라자

자라자

자라자

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © 자라자. Designed by Fraccino.

티스토리툴바