https://www.acmicpc.net/problem/11723
11723번: 집합
첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다. 둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.
www.acmicpc.net
비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.
첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다.
둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.
check 연산이 주어질때마다, 결과를 출력한다.
26
add 1
add 2
check 1
check 2
check 3
remove 2
check 1
check 2
toggle 3
check 1
check 2
check 3
check 4
all
check 10
check 20
toggle 10
remove 20
check 10
check 20
empty
check 1
toggle 1
check 1
toggle 1
check 1
1
1
0
1
0
1
0
1
0
1
1
0
0
0
1
0
이 문제는 vector<bool> 컨테이너로 인덱스의 값을 바꿔주는 식으로 풀 수도 있다.
그러나 비트마스크를 정리도 할겸, 훨씬 메모리 소모량이 적은 비트마스크를 써서 풀어보겠다.
정수를 비트 단위로 조작할 수 있는 연산자.
두 정수 같은 자리의 비트가 모두 1일 때 1을 반환한다.
예) 1111 & 1000 = 1000
두 정수 같은 자리의 비트가 하나라도 1이라면 1을 반환한다.
예) 1110 & 1000 = 1110
두 정수 같은 자리의 비트가 둘 중 하나만 1일 때 1을 반환한다.
예) 1110 & 1000 = 01110
하나의 정수의 비트에서 1인 것은 0으로 바꾸고, 0은 1로 바꾼다.
예 ~1010 = 0101
하나의 정수의 비트를 원하는 만큼 오른쪽, 왼쪽으로 이동시킨다.
예) 1001 >> 3 = 0001
이제 문제를 풀어보자.
S |= (1 << x)
S의 x번째 비트가 1이 될 것이다.
S &= ~(1 << x)
x의 모든 비트를 바꾼 후 S와 AND연산을 한다.
두 정수 모두 1이아니면 0을 반환하는 AND연산자 때문에 S의 x번째 비트는 무조건 0이 될 것이다.
if(S & (1 << x))
두 정수 모두 1이아니면 0을 반환하는 AND연산자로 유무를 판단한다.
S ^= (1 << x)
두 정수 중 하나만 1이어야 1을 반환하는 XOR연산자 때문에, S의 x가 0이라면 1, 1이라면 0이 될 것이다.
s = (1 << 21) - 1
1 << 21는 21자리의 비트를 가진 정수이다. 여기서 -1을 해주면 20자리의 수가 되는데, 모든 비트가 1이 된다.
간단하게 S = 0으로 초기화 해준다.
M (1 ≤ M ≤ 3,000,000) 이기 때문에 cin이 자주 발생하게 된다.
cin은 scanf보다 더 무겁기 때문에 최적화를 해줄 필요가 있었다.
ios_base::sync_with_stdio(0);
로 컴파일러가 다른 표준 입출력 버퍼의 동기화를 막아줬다.
동기화를 꺼줌으로써 c++은 자기만의 버퍼를 사용할 수 있다.
그러나 멀티 스레드 환경에서는 데이터 레이스 가능성이 있기 때문에 안전하지는 않다. 때에 따라 쓰는게 좋겠다.
cin.tie(0);
cin과 cout는 매번 buffer를 비우는 작업을 한다.
너무 많은 문자가 쌓일 경우를 방지하기 위함이지만, 코딩테스트같은 문제를 푸는 코드에서는 대부분 사용할 일이 없다.
그래서 위 코드로 buffer를 비우는걸 방지해줬다. 그러나 위와 마찬가지로 데이터 레이스의 가능성이 있기 때문에 적절히 사용해야 한다.
#include <iostream>
#define endl '\n'
using namespace std;
void solution(string command, int &bit)
{
int x = 0;
if (command != "all" && command != "empty") // all, empty 인 경우에 x 입력을 받지 않는다.
cin >> x;
if (command == "add")
{
bit |= (1 << x); // x
}
else if (command == "remove")
{
bit &= ~(1 << x);
}
else if (command == "check")
{
if (bit & (1 << x))
cout << "1" << endl;
else cout << "0" << endl;
return;
}
else if (command == "toggle")
{
bit ^= (1 << x);
}
else if (command == "all")
{
bit = (1 << 21) - 1;
}
else if (command == "empty")
{
bit = 0;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int M;
cin >> M;
int bit = 0;
for (int i = 0; i < M; ++i)
{
string command;
cin >> command;
solution(command, bit);
}
}
[DFS] 백준 4963 - 섬의 개수 (0) | 2022.04.12 |
---|---|
[DFS] 백준 13023 - ABCDE (0) | 2022.04.11 |
[순열] 백준 15661 - 링크와 스타트 (0) | 2022.04.08 |
[순열] 백준 10971 - 외판원 순회2 (0) | 2022.04.07 |
[순열] 백준 15649 - N과 M1 (0) | 2022.04.05 |