Stunning Garbanzo
open main menu
Part of series: PS

22866 BOJ

/ 2 min read

문제

접근

스택을 이용해 해결하였다.

정렬되어 있는 스택, 모노톤(단조) 스택을 이용해 해결하였다. 오른쪽을 바라봤을 경우와 왼쪽을 바라봤을 경우로 나누어 조사해야 한다. 스택에 현재 높이보다 큰 값들만 들어가게끔 스택을 조정하면, 조정된 스택의 크기가 현재 위치에서 바라볼 수 있는 건물의 개수이다. 현재 건물의 높이를 스택에 넣어주고 다음 건물에서 바라볼 수 있는 건물의 개수를 조사하면 된다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef const ll cll;

cll N = 1e5, L = 1e5;
ll n, heights[N] = {}, avail[N][2] = {{}}, near[N][2] = {{}};

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  cin >> n;
  for (ll i = 0; i < n; ++i) {
    cin >> heights[i];
  }

  stack<pll> s0;
  for (ll i = n - 1; i >= 0; --i) {
    while (!s0.empty()) {
      if (s0.top().first <= heights[i]) {
        s0.pop();
      } else {
        break;
      }
    }

    avail[i][0] = s0.size();
    near[i][0] = s0.empty() ? -1 : s0.top().second;

    s0.push({heights[i], i});
  }

  stack<pll> s1;
  for (ll i = 0; i < n; ++i) {
    while (!s1.empty()) {
      if (s1.top().first <= heights[i]) {
        s1.pop();
      } else {
        break;
      }
    }

    avail[i][1] = s1.size();
    near[i][1] = s1.empty() ? -1 : s1.top().second;
    s1.push({heights[i], i});
  }

  for (ll i = 0, navail; i < n; ++i) {
    navail = avail[i][0] + avail[i][1];
    cout << navail << " ";
    if (near[i][0] != -1 && near[i][1] != -1) {
      ll dist0 = near[i][0] - i, dist1 = i - near[i][1];
      if (dist1 <= dist0) {
        cout << near[i][1] + 1;
      } else {
        cout << near[i][0] + 1;
      }
    } else if (near[i][0] != -1) {
      cout << near[i][0] + 1;
    } else if (near[i][1] != -1) {
      cout << near[i][1] + 1;
    }
    cout << "\n";
  }

  return 0;
}