목차

백설공주와 난쟁이

ps
링크acmicpc.net/…
출처BOJ
문제 번호2912
문제명백설공주와 난쟁이
레벨플래티넘 3
분류

구간 쿼리

시간복잡도O(logn)
인풋사이즈n<=300,000
사용한 언어Python
제출기록74140KB / 1288ms
최고기록1068ms
해결날짜2021/05/03

풀이

코드

코드 1 - 랜덤에 기반한 방법

"""Solution code for "BOJ 2912. 백설공주와 난쟁이".

- Problem link: https://www.acmicpc.net/problem/2912
- Solution link: http://www.teferi.net/ps/problems/boj/2912
"""

import bisect
import random
import sys

REPEAT_COUNT = 50


def main():
    N, C = [int(x) for x in sys.stdin.readline().split()]
    colors = [int(x) for x in sys.stdin.readline().split()]
    indexes = [[] for _ in range(C)]
    for i, color in enumerate(colors):
        indexes[color - 1].append(i)
    M = int(sys.stdin.readline())
    for _ in range(M):
        A, B = [int(x) for x in sys.stdin.readline().split()]
        for _ in range(REPEAT_COUNT):
            cand = colors[random.randrange(A - 1, B)]
            cand_indexes = indexes[cand - 1]
            count = (bisect.bisect_left(cand_indexes, B) 
                     - bisect.bisect_left(cand_indexes, A - 1))
            if count > (B - A + 1) // 2:
                print('yes', cand)
                break
        else:
            print('no')


if __name__ == '__main__':
    main()

코드 2 - 구간 중간값을 이용한 방법

"""Solution code for "BOJ 2912. 백설공주와 난쟁이".

- Problem link: https://www.acmicpc.net/problem/2912
- Solution link: http://www.teferi.net/ps/problems/boj/2912
"""

import bisect
import operator
import sys


class MergeSortTreeForKthElem:
    def __init__(self, values):
        l = [[i] for i, value
             in sorted(enumerate(values), key=operator.itemgetter(1))]
        self._values = values
        self._size = 1 << (len(l) - 1).bit_length()
        self._tree = ([[] for _ in range(self._size)]
                      + l + [[]] * (self._size - len(l)))
        for i in range(self._size - 1, 0, -1):
            self._tree[i] = self._tree[i * 2] + self._tree[i * 2 + 1]
            self._tree[i].sort()

    def kth(self, beg: int, end: int, k: int) -> int:
        i = 1
        while i < self._size:
            i += i
            node = self._tree[i]
            t = bisect.bisect_left(node, end) - bisect.bisect_left(node, beg)
            if t < k:
                k -= t
                i += 1
        return self._values[self._tree[i][0]]


def main():
    N, C = [int(x) for x in sys.stdin.readline().split()]
    colors = [int(x) for x in sys.stdin.readline().split()]
    indexes = [[] for _ in range(C)]
    for i, color in enumerate(colors):
        indexes[color - 1].append(i)
    mst = MergeSortTreeForKthElem(colors)
    M = int(sys.stdin.readline())
    for _ in range(M):
        A, B = [int(x) for x in sys.stdin.readline().split()]
        median = mst.kth(A - 1, B, (B - A) // 2 + 1)
        ind = indexes[median - 1]
        count = bisect.bisect_left(ind, B) - bisect.bisect_left(ind, A - 1)
        if count > (B - A + 1) // 2:
            print('yes', median)
        else:
            print('no')


if __name__ == '__main__':
    main()