Categories: CompetitionKickstart

Google Kickstart 2019 Round D – ‘X or What’ 풀이 (코드포함)

이 포스팅에서는 Google Kickstart 2019 Round D ‘X or What’의 풀이와 코드를 제공합니다.
본 풀이는 공식적인 풀이와 완벽히 일치하지 않을 수 있으며, 온라인 Submission을 통과하였습니다.
공식 풀이 및 자세한 사항은 공식 페이지를 참조하시기 바랍니다.


Prob A ‘X or What’

문제 정보

문제 링크 : https://codingcompetitions.withgoogle.com/kickstart/round/0000000000051061/0000000000161426
카테고리 : Bit manipulation, Heap
난이도 : 중간

문제 설명

테스트 케이스의 수 T가 주어진다.
그 다음 줄에는 배열의 길이 N과 쿼리의 수 Q가 주어진다.
그 다음 줄에는 배열의 원소인 정수 A_0, A_1, … , A_N-1이 입력된다.
그 다음 Q개의 줄에는 배열 인덱스와 새로운 값을 가리키는 P_i, V_i가 입력된다.
이 쿼리의 연산은 A[P_i]의 값을 V_i로 바꾸는 연산이다.
각 쿼리를 수행한 후, 배열 A의 SubArray 중 모든 원소를 Xor해서 2진수로 표현할 때 1이 짝수 개인 SubArray 중 가장 긴 것의 길이를 출력하여라.

예를 들어, 원래 배열이 3 3 3 3 3 3 3 3 3 3 이라고 하자.
여기서 쿼리 1 4 를 수행하면 3 4 3 3 3 3 3 3 3 3 의 배열을 얻는다.
여기서 가능한 가장 긴 SubArray는 인덱스 (2, 9)의 구간인 3 3 3 3 3 3 3 3 이다.
따라서 길이 8이 출력된다.
여기서 쿼리 2 4를 수행하면 3 4 4 3 3 3 3 3 3 3 을 얻는다.
여기서 가장 가능한 긴 SubArray는 인덱스 (0, 9)의 구간인 3 4 4 3 3 3 3 3 3 3 이다.
따라서 길이 10을 출력한다.

문제 풀이

2진수로 표현했을 때, 비트 수가 홀수 인 것을 odd, 짝수인 것을 even이라고 하자.
문제 해결의 핵심 아이디어는 odd와 odd를 xor하면 even이 된다는 점이다.
예를 들어 7(111)과 4(100)를 xor하면 3(11)이 된다. 증명은 간단하다.
두 수가 공유하는 1의 비트는 xor로 사라진다. 서로 공유하지 않는 1의 비트는 xor 결과에서 별개로 존재하므로 그 수를 각각 더해야한다.
공유하는 1의 비트가 짝수라면 서로 공유하지 않는 1의 비트는 각각 홀수개라 더하면 짝수가된다.
공유하는 1의 비트가 홀수개라도 남은 비트가 각각 짝수이므로 역시 더하면 짝수가된다.

즉, 결론은 다음과 같다.
쿼리를 수행한 이후에 배열의 odd가 짝수개 있으면 배열의 길이 자체가 답이된다.
만약 odd가 홀수 개 있다면, 배열의 가장 왼쪽이나 오른쪽의 원소까지를 제외한 나머지 길이 중 큰 것이 답이된다.

코드
import Queue

def countBit(N):
    ret = 0
    while N > 0:
        ret += (N % 2)
        N //= 2
    return ret % 2

def findMaxLength(Min_Q, Max_Q, Nums, N):
    left, right = None, None
    while not Min_Q.empty():
        idx, val = Min_Q.get()
        if Nums[idx] == val:
            left = [idx, val]
            Min_Q.put([idx, val])
            break
    
    while not Max_Q.empty():
        idx, val = Max_Q.get()
        if Nums[-idx] == val:
            right = [-idx, val]
            Max_Q.put([idx, val])
            break
    
    if N - left[0] - 1 > right[0]:
        return N - left[0] - 1
    else:
        return right[0]
        
        
T = int(input())
for case in range(1, T + 1):
    # Get Input
    N, Q = [int(x) for x in raw_input().split(' ')]
    Nums = [int(x) for x in raw_input().split(' ')]
    
    # Init Priority Queue
    Min_Q = Queue.PriorityQueue()
    Max_Q = Queue.PriorityQueue()
    oddCnt = 0
    
    # Calc initial state of array
    for i in range(N):
        if countBit(Nums[i]) == 1:
            oddCnt += 1
            Min_Q.put([i, Nums[i]])
            Max_Q.put([-i, Nums[i]])

    result = []
    # For each query, handle element according oddness of bits.
    for i in range(Q):
        idx, newVal = [int(x) for x in raw_input().split(' ')]
        if countBit(newVal) == 1:
            Min_Q.put([idx, newVal])
            Max_Q.put([-idx, newVal])
            if countBit(Nums[idx]) == 0:
                oddCnt += 1
        elif countBit(newVal) == 0:
            if countBit(Nums[idx]) == 1:
                oddCnt -= 1
        Nums[idx] = newVal
        
        # If number of oddbits is odd, calc max length.
        if oddCnt % 2 == 0:
            result.append(str(N))
        else:
            result.append(str(findMaxLength(Min_Q, Max_Q, Nums, N)))
    
    print "Case #" + str(case) + ": " + " ".join(result)

Competition Kickstart ‘X or What’

admin

Recent Posts

2025년 10월 12일 일요일 – 서울 생활 176주차

AI AI Agent들이 어느 정도 유용한 건 맞지만, 생각보다 성능이 그렇게 시원찮은지는 모르겠다. 특히나 코드…

2개월 ago

2025년 9월 21일 일요일 – 서울 생활 173주차

중간 점검 시간이 얼마나 빠른지 여름이 훌쩍 지나 3분기는 이제 겨우 한 주가 남아, 올해의…

3개월 ago

2025년 9월 7일 일요일 – 서울 생활 171주차

금주 금주를 시작해보기로 했다. 이미 술을 먹기로 하고 잡은 2개의 회식들은 예외로 하고, 나머지 자리에서는…

3개월 ago

2025년 8월 31일 일요일 – 서울 생활 170주차

티앤미미 예약이 그렇게 힘들다는 티앤미미를 처남네가 운좋게 예약해서 어제 저녁 다녀왔다. 딤섬이 그렇게 맛있다고 하는데,…

3개월 ago

2025년 8월 17일 일요일 – 서울 생활 168주차

아난티 부산 시설과 고객 서비스가 이렇게 극단적으로 다른 방향인 호텔이 있을까 싶다. 시설의 퀄리티는 5성급이라기에…

4개월 ago

2025년 8월 3일 일요일 – 서울 생활 166주차

스트레스 관리 ENTJ 성격 특인지는 몰라도, 나는 계획했던 일에 변수가 생기면 그 순간 큰 스트레스를…

4개월 ago

This website uses cookies.