PS

[C++] 카드 게임 (백준 16566번)

jungh150c 2025. 6. 23. 01:37

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

 

#include <iostream>
#include <set>
using namespace std;

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

    int n, m, k;
    cin >> n >> m >> k;

    set<int> blue;
    for (int i = 0; i < m; i++) {
        int x;
        cin >> x;
        blue.insert(x);
    }

    for (int i = 0; i < k; i++) {
        int x;
        cin >> x;
        auto it = blue.upper_bound(x);
        cout << *it << '\n';
        blue.erase(it);
    }
}

(TLE)

단순히 수들을 set에 넣어두고 upper_bound로 수를 찾고 지워주고...를 반복하면 시간 초과를 받는다.

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> parent;

int find(int a) {
    if (parent[a] == a) return a;
    else return parent[a] = find(parent[a]);
}

void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if (a != b) parent[a] = b;
}

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

    int n, m, k;
    cin >> n >> m >> k;

    vector<int> blue(m);
    for (int i = 0; i < m; i++) cin >> blue[i];
    sort(blue.begin(), blue.end());

    parent = vector<int>(m);
    for (int i = 0; i < m; i++) parent[i] = i;

    for (int i = 0; i < k; i++) {
        int x;
        cin >> x;
        int tidx = upper_bound(blue.begin(), blue.end(), x) - blue.begin();
        int chosen = find(tidx);
        cout << blue[chosen] << '\n';
        if (chosen + 1 < m) unite(chosen, chosen + 1);
    }
}

(AC)

그래서 수를 삭제하는 연산 대신 그 수를 사용했다면 그 수 다음 수를 써야 한다고 표시해주는 작업을 유니온 파인드를 이용하여 해주었다. 나는 민수의 카드 배열 blue의 인덱스를 기준으로 유파를 해줬다. 아이디어 떠올리는 게 어렵다 ㅜ.ㅜ