BOJ 34905 Quantum Beaver

BOJ 34905 Quantum Beaver

문제 링크:

문제 내용

최초에 0으로 채워진 길이 NN의 1차원 배열이 있습니다. 당신은 어떤 계획에 따라 배열의 값을 바꾸려고 합니다. 이 계획은 QQ개의 단위 계획으로 이루어져 있으며, 하나의 단위 계획은 다음과 같습니다.

  • (di,xi,yi,ci)(d_i, x_i, y_i, c_i) (0di<2K0 \le d_i < 2^K, 1xiyiN1 \le x_i \le y_i \le N, 0ci1090 \le c_i \le 10^9) : did_i번째 날에, 배열의 xix_i번째부터 yiy_i번째까지의 원소를 cic_i로 바꿉니다.

did_i들은 모두 서로 다릅니다.

그런데 당신은 라플라스의 악마의 저주에 걸렸기 때문에, 이 계획을 실행하기 전에 모든 단위 계획의 did_idird_i \oplus r로 바뀌게 됩니다. rr00 이상 2K2^K 미만의 정수 중에서 랜덤으로 정해진 수입니다.

rr의 값이 정해졌을 때 최종 배열의 모든 원소의 합을 f(r)f(r)이라고 할 때, r=02K1f(r)\sum_{r=0}^{2^K - 1} f(r)의 값을 구하세요.

입력

첫 줄에는 테스트 케이스의 개수 TT가 주어집니다. (1T1501 \le T \le 150)

각 테스트 케이스의 첫 줄에는 NN, KK, QQ가 주어집니다. (1N200  0001 \le N \le 200\;000, 0K600 \le K \le 60, 1 \le Q \le \min(2^K, 200;000)$)

그 다음 QQ줄에 걸쳐서 각 줄에 하나의 단위 계획을 나타내는 did_i, xix_i, yiy_i, cic_i가 주어집니다.

NN의 총합과 QQ의 총합은 각각 400  000400\;000을 초과하지 않습니다.

출력

각 테스트 케이스에 대해, 문제의 정답을 1  000  000  0071\;000\;000\;007로 나눈 나머지를 한 줄에 출력합니다.

문제 풀이

스포일러

이 문제는 비트 트라이에 세그먼트 트리를 얹어서 풀 수 있습니다.

N=1N = 1인 경우의 문제를 풀 수 있고 각각의 did_i를 넣고 빼는 쿼리를 처리할 수 있다면, 문제가 요구하는 식에서 합의 순서를 바꿔 1번째 원소가 가질 수 있는 가능한 모든 수의 합, …, NN번째 원소가 가질 수 있는 가능한 모든 수의 합을 구해서 문제를 풀 수 있을 것입니다.

배열에서 어떤 자리가 최종적으로 cic_i가 되는 경우의 수는 다음과 같이 구해집니다.

  • djd_j들 중에서 K1K-1번째 비트가 cic_i와 다른 것이 있다면, 그 비트는 XOR 결과 1이 되어야 하므로 전체 경우의 수가 절반으로 나눠집니다.
  • 그러한 것이 없다면 전체 경우의 수는 그대로 다음 비트로 전파됩니다. 이는 역으로 생각하면 그 비트를 제외한 2K12^{K-1}가지 중에서 계산한 경우의 수에 2배를 한 것과 같습니다.
  • 트라이를 따라가면서 이 과정을 반복합니다.

일단 did_i의 목록이 사전에 정해져 있으므로 이들 값을 모두 포함하는 트라이를 만들고, 각 노드에 대해 그 노드에서 도달할 수 있는 리프 중에서 현재 켜져 있는 did_i의 개수를 저장합니다. 그러면 각 노드에서 그 노드 아래의 리프들이 총합에 기여하는 값을 세그먼트 트리와 같은 방식으로 구할 수 있습니다.

  • 리프에는 cic_i를 저장합니다.
  • 어떤 노드의 자식이 두 개이고 그 둘이 모두 비어 있지 않다면, 양쪽의 값을 더해 줍니다.
  • 둘 중 한 쪽이 비어있다면, 반대쪽 값을 2배 해서 저장합니다. 둘 다 비어있다면 이 노드의 값은 0입니다.
  • 자식이 한 개라면 그 자식의 값을 2배 해서 저장합니다.

did_i를 하나 켜고 끄는 업데이트는 리프를 먼저 업데이트하고 루트 방향으로 따라가면서 모든 값을 업데이트해주면 됩니다. 이 업데이트를 이용해서 배열의 인덱스 방향으로 스위핑하여 각 인덱스에서의 총합을 모두 구하면 문제의 정답을 구할 수 있습니다.

이대로 구현 시 마지막 서브태스크에서 시간 초과를 받는다면, 연속으로 자식이 한 개인 구간들을 한 번에 건너뛸 수 있도록 추가 처리를 해주면 통과합니다.

Last updated on