結果

問題 No.2686 商品券の使い道
ユーザー LyricalMaestroLyricalMaestro
提出日時 2024-10-30 01:57:29
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 378 ms / 3,000 ms
コード長 4,566 bytes
コンパイル時間 328 ms
コンパイル使用メモリ 82,312 KB
実行使用メモリ 98,084 KB
最終ジャッジ日時 2024-10-30 01:57:41
合計ジャッジ時間 11,795 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 38 ms
54,100 KB
testcase_01 AC 37 ms
53,508 KB
testcase_02 AC 75 ms
75,828 KB
testcase_03 AC 82 ms
76,168 KB
testcase_04 AC 76 ms
75,968 KB
testcase_05 AC 77 ms
76,028 KB
testcase_06 AC 75 ms
76,180 KB
testcase_07 AC 76 ms
75,700 KB
testcase_08 AC 74 ms
75,792 KB
testcase_09 AC 75 ms
75,780 KB
testcase_10 AC 76 ms
75,944 KB
testcase_11 AC 188 ms
83,372 KB
testcase_12 AC 132 ms
78,476 KB
testcase_13 AC 167 ms
82,924 KB
testcase_14 AC 187 ms
81,752 KB
testcase_15 AC 173 ms
81,596 KB
testcase_16 AC 183 ms
83,524 KB
testcase_17 AC 166 ms
80,716 KB
testcase_18 AC 161 ms
82,068 KB
testcase_19 AC 156 ms
81,488 KB
testcase_20 AC 156 ms
82,692 KB
testcase_21 AC 186 ms
83,092 KB
testcase_22 AC 145 ms
79,584 KB
testcase_23 AC 111 ms
77,536 KB
testcase_24 AC 183 ms
82,396 KB
testcase_25 AC 116 ms
78,652 KB
testcase_26 AC 160 ms
81,200 KB
testcase_27 AC 164 ms
82,324 KB
testcase_28 AC 84 ms
76,664 KB
testcase_29 AC 192 ms
80,636 KB
testcase_30 AC 282 ms
95,300 KB
testcase_31 AC 314 ms
92,236 KB
testcase_32 AC 332 ms
97,052 KB
testcase_33 AC 293 ms
95,448 KB
testcase_34 AC 191 ms
80,796 KB
testcase_35 AC 282 ms
93,340 KB
testcase_36 AC 335 ms
98,040 KB
testcase_37 AC 368 ms
97,712 KB
testcase_38 AC 320 ms
95,432 KB
testcase_39 AC 333 ms
96,172 KB
testcase_40 AC 334 ms
94,260 KB
testcase_41 AC 143 ms
77,756 KB
testcase_42 AC 378 ms
97,168 KB
testcase_43 AC 350 ms
97,696 KB
testcase_44 AC 351 ms
97,480 KB
testcase_45 AC 323 ms
95,428 KB
testcase_46 AC 359 ms
98,084 KB
evil_random20_1.txt AC 102 ms
76,188 KB
evil_random20_2.txt AC 107 ms
76,488 KB
evil_random20_3.txt AC 103 ms
76,400 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

## https://yukicoder.me/problems/no/2686


class SegmentTree:
    """
    非再帰版セグメント木。
    更新は「加法」、取得は「最大値」のもの限定。
    """

    def __init__(self, init_array):
        n = 1
        while n < len(init_array):
            n *= 2
        
        self.size = n
        self.array = [[] for _ in range(2 * self.size)]
        for i, q_array in enumerate(init_array):
            self.array[self.size + i] = q_array
        
        end_index = self.size
        start_index = end_index // 2
        while start_index >= 1:
            for i in range(start_index, end_index):
                self.array[i] = self._fill(self.array[2 * i], self.array[2 * i + 1])
            end_index = start_index
            start_index = end_index // 2

    def _fill(self, left, right):
        q_map = {}
        for l, v in left:
            q_map[l]= v
        for r, v in right:
            if r not in q_map:
                q_map[r] = 0
            q_map[r] = max(v, q_map[r])
        q_array = [(q, v) for q, v in q_map.items() ]
        q_array.sort(key=lambda x : x[0])
        return q_array


    def add(self, x, a):
        index = self.size + x
        self.array[index] += a
        while index > 1:
            index //= 2
            self.array[index] = max(self.array[2 * index], self.array[2 * index + 1])

    def find(self, array, q):
        if len(array) == 0:
            return  0
        
        if array[0][0] > q:
            return 0
        
        low = 0
        high = len(array) - 1
        while high - low > 1:
            mid = (high + low) // 2
            if array[mid][0] <= q:
                low = mid
            else:
                high = mid
        if array[high][0] <= q:
            return array[high][1]
        else:
            return array[low][1]

    def get_max(self, l, r, q):
        L = self.size + l; R = self.size + r

        # 2. 区間[l, r)の最大値を求める
        s = 0
        while L < R:
            if R & 1:
                R -= 1

                s = max(s, self.find(self.array[R], q))
            if L & 1:
                s = max(s, self.find(self.array[L], q))
                L += 1
            L >>= 1; R >>= 1
        return s



def solve(N, M, Q, ab):
    if N == 1:
        A, B = ab[0]
        if A <= M and B <= Q:
            return A + B
        else:
            return 0
        
    n1 = N // 2
    n2 = N - n1
    # n1の全列挙
    n1_array = []
    for bit3 in range(3 ** n1):
        p = 0
        q = 0
        value = 0
        for i in range(n1):
            a = bit3 % 3
            if a == 1:
                p += ab[i][0]
                value += ab[i][1]
            elif a == 2:
                q += ab[i][0]
                value += ab[i][1]

            bit3 //= 3
        if p <= M and q <= Q:
            n1_array.append((p, q, value))
    
    # n2の方をseqmenttreeに格納する
    p_q_map = {}
    for bit3 in range(3 ** n2):
        p = 0
        q = 0
        value = 0
        for i in range(n2):
            a = bit3 % 3
            if a == 1:
                p += ab[n1 + i][0]
                value += ab[n1 + i][1]
            elif a == 2:
                q += ab[n1 + i][0]
                value += ab[n1 + i][1]

            bit3 //= 3

        if p <= M and q <= Q:
            if p not in p_q_map:
                p_q_map[p] = {}
            if q not in p_q_map[p]:
                p_q_map[p][q] = -1
            p_q_map[p][q] = max(p_q_map[p][q], value)

    # Pについての座標圧縮
    p_set = set()
    for p, _, _ in n1_array:
        p_set.add(M - p)
    for p in p_q_map.keys():
        p_set.add(p)
    p_list = list(p_set)
    p_list.sort()
    p_map = {}
    for i, p in enumerate(p_list):
        p_map[p] = i

    # SegmentTree構築s
    p_q_array = [[] for _ in range(len(p_list)) ]
    for p, q_map in p_q_map.items():
        q_array = [ (q, v) for q, v in  q_map.items() ]
        q_array.sort(key=lambda x: x[0])
        p_q_array[p_map[p]] = q_array

    # SegmentTree
    seg_tree = SegmentTree(p_q_array)
    answer= 0
    for p, q, v in n1_array:
        max_value =  seg_tree.get_max(0, p_map[M - p] + 1, Q - q)
        ans = v + max_value
        answer = max(ans, answer)
    return answer




        
    



def main():
    N, M, Q = map(int, input().split())
    ab = []
    for _ in range(N):
        A, B = map(int, input().split())
        ab.append((A, B))

    ans = solve(N, M, Q, ab)
    print(ans)





if __name__ == "__main__":
    main()
0