문제 링크: https://acmicpc.net/problem/13021 

 

13021번: 공 색칠하기

공 N개가 한 줄로 놓여져 있다. 공은 검정색 또는 흰색으로 칠할 수 있으며, 처음에 모든 공의 색은 흰색이다. 공은 가장 왼쪽이 1번이고, 순서대로 번호가 매겨져 있다. 오늘은 공을 칠해보려고

www.acmicpc.net


문제를 요약해봅시다.

  • 입력 $L, R$에 대하여 구간 $[L, R]$에 속하는 모든 공을 흰색 또는 검은색으로 칠합니다.
  • $M$번의 색칠 후 나올 수 있는 색의 조합의 개수를 구합니다.

어떤 공이 있을 때 이 공을 몇 번 칠하든 반드시 마지막으로 색칠한 것만이 남습니다.

즉, 마지막으로 색칠한 것이 언제 칠한 것인지를 각각의 공에 대해 구해주면 됩니다.

 

$M$번을 다 칠하고 나면 각 공이 언제 마지막으로 칠해졌는지를 알 수 있습니다. 마지막으로 칠해진 시점이 같은 공들은 반드시 같은 색을 갖게 되므로, 서로 다른 칠해진 시점의 개수를 찾아줍시다.

각 시점마다 총 2가지의 색으로 칠하는 경우가 있으므로, 시점이 $K$개일 때 답은 $2^K$가 됩니다.

 

정답이 $2^{63} - 1$이하임이 보장된다고 했으므로 비트 시프트 연산으로 간단하게 답을 구할 수 있습니다.

단 64비트 자료형을 사용해야 올바른 답을 얻을 수 있습니다.

 

시간복잡도는, 총 $M$번 최대 $N$개의 공에 대해 계산을 하는 $O(MN)$의 과정과, 공을 순회하며 서로 다른 시점의 개수를 찾는 $O(N)$의 과정이 있으므로 $O(MN) + O(N) = O(MN)$ 입니다.


소스코드 (C++)

더보기
#include <bits/stdc++.h>

#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

using namespace std;
typedef long long ll;

int main() {
    fastio;
    
    int n, k;
    cin >> n >> k;
    
    vector<int> recent_color(n + 1);
    
    for (int i = 1; i <= k; i++) {
        int l, r;
        cin >> l >> r;
        
        for (int j = l; j <= r; j++) {
            recent_color[j] = i;
        }
    }
    
    vector<bool> appeared(n + 1);
    int distincts = 0;
    
    for (int i = 1; i <= n; i++) {
        if (recent_color[i] > 0 && !appeared[recent_color[i]]) {
            appeared[recent_color[i]] = true;
            distincts++;
        }
    }
    
    cout << (1LL << distincts);
    
    return 0;
}

'Problem Solving > 백준' 카테고리의 다른 글

백준 28251 - 나도리합  (0) 2023.09.27
백준 27925 - 인덕션  (0) 2023.09.26
백준 2482 - 색상환  (0) 2023.09.24
백준 7983 - 내일 할거야  (0) 2023.09.23
백준 13164 - 행복 유치원  (0) 2023.09.23

+ Recent posts