[ MR 02. 백준 - 24511. queuestack ]

yeahzxnn·2024년 7월 5일
0
post-thumbnail

[ MR 01. 백준 - 24511. queuestack ]

Making Routine Series : MR
02. 백준 : 24511. queuestack

습관처럼 만들기 위해 쓰는 포스트입니다!


문제

한가롭게 방학에 놀고 있던 도현이는 갑자기 재밌는 자료구조를 생각해냈다. 그 자료구조의 이름은 queuestack이다.
queuestack의 구조는 다음과 같다.
11번,
22번, ... ,
NN번의 자료구조(queue 혹은 stack)가 나열되어있으며, 각각의 자료구조에는 한 개의 원소가 들어있다.
queuestack의 작동은 다음과 같다.
x0x_0을 입력받는다.
x0x_0
11번 자료구조에 삽입한 뒤
11번 자료구조에서 원소를 pop한다. 그때 pop된 원소를
x1x_1이라 한다.
x1x_1
22번 자료구조에 삽입한 뒤
22번 자료구조에서 원소를 pop한다. 그때 pop된 원소를
x2x_2이라 한다.
...
xN1x_{N-1}
NN번 자료구조에 삽입한 뒤
NN번 자료구조에서 원소를 pop한다. 그때 pop된 원소를
xNx_N이라 한다.
xNx_N을 리턴한다.
도현이는 길이
MM의 수열
CC를 가져와서 수열의 원소를 앞에서부터 차례대로 queuestack에 삽입할 것이다. 이전에 삽입한 결과는 남아 있다. (예제
11 참고)
queuestack에 넣을 원소들이 주어졌을 때, 해당 원소를 넣은 리턴값을 출력하는 프로그램을 작성해보자.

[ 입력 조건 ]

첫째 줄에 queuestack을 구성하는 자료구조의 개수
NN이 주어진다. (1N1000001 \leq N \leq 100\,000)
둘째 줄에 길이 NN의 수열 AA가 주어진다.
ii번 자료구조가 큐라면
Ai=0A_i = 0, 스택이라면
Ai=1A_i = 1이다.
셋째 줄에 길이 NN의 수열 BB가 주어진다.
BiB_iii번 자료구조에 들어 있는 원소이다.
(1Bi10000000001 \leq B_i \leq 1\,000\,000\,000)
넷째 줄에 삽입할 수열의 길이 MM이 주어진다.
(1M1000001 \leq M \leq 100\,000)
다섯째 줄에 queuestack에 삽입할 원소를 담고 있는 길이
MM의 수열 CC가 주어진다.
(1Ci10000000001 \leq C_i \leq 1\,000\,000\,000)
입력으로 주어지는 모든 수는 정수이다.

[출력]

각 테스트 케이스마다 ‘#x’(x는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고, P채널과 T채널 모두 구독하고 있는 사람의 수의 최댓값과 최솟값을 공백 하나를 사이로 두고 차례대로 출력한다.
#1 3 0
#2 5 2
#3 100 100


[ 내가 푼 답 ]

#include <iostream>
#include <vector>
#include <queue>
#include <stack>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N,M;
    cin >> N;
    
    vector<int> type(N); // 0이면 스택, 1이면 큐
    vector<int> initial(N); //배열 각 자료구조 초기 원소값 저장
    
    for(int i=0; i<N; ++i){
        cin >> type[i];
    }
    
    for(int i=0; i<N; ++i){
        cin >> initial[i];
    }
    
    cin >> M;
    vector<int> C(M);
    for(int i=0; i<M; i++) {
        cin >> C[i]; //queuestack에 넣을 원소들의 수열
    }
    
    //자료구조를 vector of deque로 사용
    vector<deque<int>> ds(N); //각 자료구조 deque 사용해 초기화 - 큐와 스택의 기능 모두 지원
    for(int i=0; i<N; ++i) {
        ds[i].push_back(initial[i]);
    }
    
    vector<int> results; //결과값 저장할 벡터
    
    //C원소 처리
    for(int i=0; i<M; ++i){
        int current = C[i];
        for(int j=0; j<N; ++j) {
            if (type[j] == 0) {
                // 스택 (LIFO)
                ds[j].push_back(current);
                current = ds[j].back();
                ds[j].pop_back();
            } else {
                //큐(FIFO)
                ds[j].push_back(current);
                current = ds[j].front();
                ds[j].pop_front();
            }
        }
        results.push_back(current);
    }
    
    //결과값 출력
    for(int res : results) {
        cout << res << " ";
    }
    
    return 0;
}

이렇게 풀었더니 시간초과났음...

(승헌쓰) Retry...

2트 - 시간초가 안 남...

#include <iostream>
#include <deque>

using namespace std;

deque<int> dq; // 덱을 이용하여 큐와 스택의 동작을 구현
int n, m; // n: 자료구조의 수, m: 수열의 길이
bool flag[100001]; // 자료구조의 타입을 저장하는 배열, 0: queue, 1: stack

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    cin >> n; // 자료구조의 수 입력
    for(int i = 0; i < n; i++){
        cin >> flag[i]; // 각 자료구조의 타입 입력
    }
    
    for(int i = 0; i < n; i++){
        int x;
        cin >> x; // 각 자료구조의 초기 원소 값 입력
        if(flag[i] == 0) // 자료구조가 큐일 때만 덱에 원소 삽입
            dq.push_back(x);
    }
    
    cin >> m; // 수열의 길이 입력
    for(int i = 0; i < m; i++){
        int y;
        cin >> y; // 수열의 각 원소 입력
        dq.push_front(y); // 덱의 앞에 새 원소 삽입
        cout << dq.back() << " "; // 덱의 뒤에서 원소를 출력
        dq.pop_back(); // 덱의 뒤에서 원소 제거
    }
    
    // 모든 자료구조가 스택일 경우에는 dq를 사용하지 않음
    // 수열의 각 원소에 대해 새 덱에 push_front 후 pop_back 과정 반복
    
    return 0;
}

덱에 대해서 다시 복습하고 가보자.

덱(Deque)이란?

덱(Deque, Double-Ended Queue)은 양쪽 끝에서 삽입과 삭제가 모두 가능한 자료구조. 즉, 앞쪽(front)과 뒤쪽(back)에서 모두 삽입(push)과 삭제(pop) 연산가능. 덱은 스택과 큐의 기능 모두 포함!!!

덱(Deque)을 왜 쓸까?

효율적인 양방향 접근: 덱은 양쪽 끝에서 삽입과 삭제가 가능하기 때문에, 특정 상황에서 매우 효율적.
다양한 용도: 스택, 큐, 또는 둘의 혼합된 형태로 사용가능.

이 문제에서 덱(Deque)이 사용된 이유

초기 자료구조 상태 저장:

문제에서는 각 자료구조가 초기 상태로 고정되어 있고, 새로운 원소가 삽입될 때마다 덱을 이용하여 큐 또는 스택의 동작을 구현.
초기 자료구조가 큐인 경우에만 덱에 초기 값을 저장하여 이후 연산에서 사용.

수열 처리:

각 수열 원소에 대해 덱의 앞쪽(front)에 값을 삽입하고, 덱의 뒤쪽(back)에서 값을 빼내어 출력.

덱 연산 알아보고 가자

push_front: 덱의 앞쪽에 원소를 삽입.
push_back: 덱의 뒤쪽에 원소를 삽입.
pop_front: 덱의 앞쪽에서 원소를 삭제.
pop_back: 덱의 뒤쪽에서 원소를 삭제.
front: 덱의 앞쪽 원소를 반환.
back: 덱의 뒤쪽 원소를 반환.

전체 코드는 아래 링크로👇🏻

백준 24511 - queuestack 전체 코드 보러 가기


[ 후기 ]

이번거 좀 쉽지 않았음...

아래 Velog보면서 도움도 받았습니다...감사드려요!
https://velog.io/@somyeong0623/%EB%B0%B1%EC%A4%80c-24511%EB%B2%88-queuestack

profile
Challenging & Growing

0개의 댓글