article thumbnail image
Published 2022. 10. 1. 17:36

문제: https://www.acmicpc.net/problem/5430

 

 

 

 

#include <bits/stdc++.h>
using namespace std;

void parse(string& arr, deque<int>& dq) {
  int num = 0;
  for (int i = 1; i + 1 < arr.size(); i++) {
    if (arr[i] == ']') break;
    if (arr[i] >= '0' && arr[i] <= '9')
      num = num * 10 + (arr[i] - '0');
    else {
      dq.push_back(num);
      num = 0;
    }
  }
  if (num != 0) dq.push_back(num);
}

void print_deque(deque<int>& dq) {
  cout << '[';
  for (int j = 0; j < dq.size(); j++)
    cout << dq[j] << (j + 1 != dq.size() ? "," : "");
  cout << ']' << '\n';
}

int t, n;
string p, arr;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> t;
  for (int i = 0; i < t; i++) {
    deque<int> dq;
    int rev = 0;
    int error = 0;
    cin >> p >> n >> arr;
    parse(arr, dq);

    for (char f : p) {
      if (f == 'R')
        rev = 1 - rev;
      else {
        if (dq.empty()) {
          error = 1;
          break;
        }
        if (rev)
          dq.pop_back();
        else
          dq.pop_front();
      }
    }
    if (error)
      cout << "error" << '\n';
    else {
      if (rev) reverse(dq.begin(), dq.end());
      print_deque(dq);
    }
  }
}

처음엔 스택을 사용해서 R연산을 처리했는데, 이렇게 했더니 시간 초과가 됐다.

O(n)에서 시간 초과가 됐으니 이보다 더 빠른 방법을 찾아야 했다.

 

이 문제는 R연산과 D연산 두 가지만 존재한다.

입력으로 [1, 2, 3, 4, ..., 10]가 주어졌다고 가정할 때,

D연산을 수행하면 [2, 3, 4, ..., 10]이고,

R연산과 D연산을 연속으로 수행하면 [9, 8, 7, ..., 1]이 된다.

 

즉 R연산을 수행한 후 D연산을 수행하는 건 배열의 가장 뒤의 원소를 삭제하는 것과 같다.

결국 이 문제는 배열의 가장 앞과 가장 뒤의 원소를 삭제하는 연산을 처리하면 되므로 deque를 사용해서 해결할 수 있다.

 

parse 함수는 입력으로 주어진 배열을 dq에 할당하는 역할을 한다.

arr[i]가 digit인 경우 int로 변환해서 num에 저장하고, arr[i]가 '(쉼표)인 경우 num을 dq에 push한다.

arr[i]가 ](닫는 대괄호)라면 반복문을 종료하고 미처 넣지 못한 num을 push해준다.

여기서 (num != 0)로 따로 분기처리 해주는 이유는 배열이 empty일 때 dq에 아무것도 할당해주지 않기 위해서다.

 

이제 p에서 수행할 함수를 하나씩 가져와서 처리해준다.

f가 R일 경우 reverse해야 하는데, 위에서 봤던대로 dq를 뒤집지 않고 맨 뒤 원소만 삭제해도 되기 때문에 rev만 체크해준다. 

=> 여기서 rev = 1 - rev로 작성한 이유는 rev가 1이라면 0이되고, 0이라면 1로 바뀌기 때문이다.

 

f가 D일 경우 원소를 삭제해야 하는데 먼저 rev를 체크해야 한다.

rev가 0이라면 뒤집히지 않았으므로 dq.pop_front()를 실행하고,

rev가 1이라면 뒤집힌 것이므로 dq.pop_back()을 실행한다.

이때 dq가 empty라면 error가 발생한 것이므로 error를 1로 바꿔주고, 반복문을 종료한다.

 

p에 열거된 함수 실행이 끝났으면 dq를 print 해야한다.

이때 error가 1이라면 "error"를 출력하고, 아니라면 print_deque 함수를 호출한다.

 

 

 

 

 

 

'알고리즘' 카테고리의 다른 글

[BOJ] 10799: 쇠막대기  (0) 2022.10.01
[BOJ] 3986: 좋은 단어  (0) 2022.10.01
[BOJ] 1021: 회전하는 큐  (0) 2022.10.01
[BOJ] 4949: 균형잡힌 세상  (0) 2022.09.30
[BOJ] 10886: 덱  (0) 2022.09.29
복사했습니다!