Algorithm
[백준] 11723. 집합 / 비트 연산
Dev_Green
2022. 11. 30. 22:07
https://www.acmicpc.net/problem/11723
11723번: 집합
첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다. 둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.
www.acmicpc.net
풀이
2진수의 각 자리를 1~20까지의 존재 여부를 담는 배열로서 사용한다. 수가 존재하면 1, 그렇지 않으면 0인 것이다.
예를 들어, 집합 S = {1, 3}이라고 한다면 2진수 첫번째 자리와 세번째 자리 숫자는 1이고 나머지 자리는 0일 것이다.
- add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.
- s |= (1 << x) : 1을 x만큼 왼쪽으로 쉬프트 연산한 결과를 s와 OR 연산하여 대입한다. 좌항, 우항 중 어느 한 쪽에라도 1이 있으면 1을 결과로 낸다.
- remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.
- s &= ~(1 << x) : 1을 x만큼 왼쪽으로 쉬프트 연산한 결과의 부정을 s와 AND 연산하여 대입한다. 좌항, 우항 모두 1이 있어야 1을 결과로 낸다.
- check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)
- s & (1 << x)) != 0 : 특정 자리 수가 1인 이진수와 s를 AND 연산했을 때 s에도 1이 있어야 1을 결과로 내고, 그렇지 않으면 0을 결과로 낸다.
- toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)
- s ^= (1 << x) : 값을 뒤집기 위해 XOR 연산을 한다.
- all: S를 {1, 2, ..., 20} 으로 바꾼다.
- s = (1 << 20) - 1 : 이진수의 첫째자리부터 20번째자리까지 모두를 1로 만든다.
- empty: S를 공집합으로 바꾼다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BOJ11723 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int M = Integer.parseInt(br.readLine());
int s = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < M; i++) {
String[] input = br.readLine().split(" ");
switch (input[0]) {
case "all":
s = (1 << 20) - 1; // 2진수 첫째자리부터 20번째자리까지 모두 1인 상태
break;
case "empty":
s = 0; // 십진수 0. 곧 이진수로도 모든 자리 숫자 0
break;
// 위 케이스들에 아무것도 해당하지 않을 때 수행될 코드
default:
int x = Integer.parseInt(input[1]) - 1;
switch (input[0]) {
case "add":
s |= (1 << x); // 좌우 항의 OR 연산 결과를 좌항에 대입
break;
case "remove":
s &= ~(1 << x); // 좌우 항의 AND 연산 결과를 좌항에 대입
break;
case "check":
sb.append((s & (1 << x)) != 0 ? 1 : 0).append('\n'); // 2진수 상에서 특정 자리 숫자가 1인지 확인
break;
case "toggle":
s ^= (1 << x); // 좌우 항의 XOR 연산 결과를 좌항에 대입
break;
}
}
}
System.out.println(sb);
}
}