백준 11723 파이썬

11723번: 집합

11723번 : 집합
알고리즘: 비트마스크

해설

해당 문제는 최대 3백만 번의 연산을 요구하는 만큼 효율적인 연산 · 메모리 사용이
필요하다.

비트마스크란(Bitmask)?
정수의 각 비트를 bool 자료형처럼 사용하여 정수 자료형을 마치 여러개의 bool로
이루어진 배열처럼 사용하는 방법이다.
일반적인 4byte int로 2^32가지 경우의 수를 표현 할 만큼 메모리 효율성이 좋다.

2진수 n자리 수를 문제의 x에 대응하면 집합S를 0b000000000000000000000로 나타낼 수 있다.
예) 집합S에 2, 5, 9, 15, 20이 들어있는경우 S = 0b100001000000000100100

아래 예시들은 편의를 위해 1 <= X <= 10으로 가정하겠다

Add X
1을 << X 한 후 S와 OR 연산한다.
예) S ={ 2, 5 } / Add 7

Bit 10 9 8 7 6 5 4 3 2 1 0
1 << 7 0 0 0 1 0 0 0 0 0 0 0
S 0 0 0 0 0 1 0 0 1 0 0
OR 0 0 0 1 0 1 0 0 1 0 0

Remove X
1을 << X 한 후 ~(not) 연산하여 S와 AND 연산한다.
예) S = { 2, 5, 7 } / Remove 7

Bit 10 9 8 7 6 5 4 3 2 1 0
1 << 7 0 0 0 1 0 0 0 0 0 0 0
~ (1 << 7) 1 1 1 0 1 1 1 1 1 1 1
S 0 0 0 1 0 1 0 0 1 0 0
AND 0 0 0 0 0 1 0 0 1 0 0

Toggle X
1을 << X 한 후 S와 XOR 연산한다.
예) S = { 2, 5, 7 } / Toggle 7

Bit 10 9 8 7 6 5 4 3 2 1 0
1 << 7 0 0 0 1 0 0 0 0 0 0 0
S 0 0 0 1 0 1 0 0 1 0 0
XOR 0 0 0 0 0 1 0 0 1 0 0

Empty X
모든 비트가 0 이므로 S = 0

All
( 1 << X_MAX + 1 ) - 1

Bits 11 10 9 8 7 6 5 4 3 2 1 0
1 << X_MAX + 1 1 0 0 0 0 0 0 0 0 0 0 0
- 1 0 1 1 1 1 1 1 1 1 1 1 1

Check
1을 << X 한 후 AND연산 결과가 0이면 없음, 0이 아니라면 있음
예) S = { 2, 5, 7 } / Check 7

Bits 10 9 8 7 6 5 4 3 2 1 0
1 << 7 0 0 0 1 0 0 0 0 0 0 0
S 0 0 0 1 0 1 0 0 1 0 0
AND 0 0 0 1 0 0 0 0 0 0 0

예) S = { 2, 5 } / Check 7

Bits 10 9 8 7 6 5 4 3 2 1 0
1 << 7 0 0 0 1 0 0 0 0 0 0 0
S 0 0 0 0 0 1 0 0 1 0 0
AND 0 0 0 0 0 0 0 0 0 0 0

코드

import sys

m = int(sys.stdin.readline())
s = 0b000000000000000000000

for i in range(m):
    arr = sys.stdin.readline().split()
    calc = arr[0]

    if calc == 'all':
        s = (1 << 21) - 1
    elif calc == 'empty':
        s = 0
    elif calc == 'add':
        s |= 1 << int(arr[1])
    elif calc == 'remove':
        s &= ~(1 << int(arr[1]))
    elif calc == 'toggle':
        s ^= (1 << int(arr[1]))
    elif calc == 'check':
        print(1 if (s & (1 << int(arr[1]))) != 0 else 0)