結果
| 問題 | No.3436 [Cherry 8th Tune B] この夏に何が起こるかな? |
| コンテスト | |
| ユーザー |
👑 Kazun
|
| 提出日時 | 2025-03-17 01:34:01 |
| 言語 | PyPy3 (7.3.17) |
| 結果 |
AC
|
| 実行時間 | 1,854 ms / 4,000 ms |
| コード長 | 3,993 bytes |
| 記録 | |
| コンパイル時間 | 461 ms |
| コンパイル使用メモリ | 82,752 KB |
| 実行使用メモリ | 127,136 KB |
| 最終ジャッジ日時 | 2026-01-23 21:14:52 |
| 合計ジャッジ時間 | 57,290 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 43 |
ソースコード
def General_Binary_Increase_Search_Integer(L, R, cond, default=None):
""" 条件式が単調増加であるとき, 整数上で二部探索を行い, cond(x) が真になる最小の整数 x を求める.
L: 解の下限
R: 解の上限
cond: 条件(1変数関数, 広義単調増加を満たす)
default: R で条件を満たさない (つまり, [L, R] 上では常に偽) ときの返り値
"""
if not(cond(R)):
return default
if cond(L):
return L
R+=1
while R-L>1:
C=L+(R-L)//2
if cond(C):
R=C
else:
L=C
return R
#==================================================
import dataclasses
@dataclasses.dataclass
class Top:
id: int
price: int
color: int
@dataclasses.dataclass
class Bottom:
id: int
price: int
color: int
#==================================================
def input_integers() -> str:
return list(map(int, input().split()))
def solve():
from operator import attrgetter
N, M, K, P = map(int, input().split())
T = input_integers()
C = input_integers()
B = input_integers()
D = input_integers()
S = [0] + input_integers()
tops = [Top(i, T[i - 1], C[i - 1]) for i in range(1, N + 1)]
tops_sort = sorted(tops, key = attrgetter('price'))
color_tops: list[list[Top]] = [[] for _ in range(K + 1)]
for top in tops_sort:
color_tops[top.color].append(top)
bottoms = [Bottom(j, B[j - 1], D[j - 1]) for j in range(1, M + 1)]
bottoms_sort = sorted(bottoms, key = attrgetter('price'))
color_bottoms: list[list[Bottom]] = [[] for _ in range(K + 1)]
for bottom in bottoms_sort:
color_bottoms[bottom.color].append(bottom)
# Section I: 「X 円以下のセットが P 組以上」を満たす最小の非負整数 X を求める.
def count_pairs_less_price(tops: list[Top], bottoms: list[Top], X: int) -> int:
res = 0
j = len(bottoms)
for top in tops:
while (j > 0) and (top.price + bottoms[j - 1].price > X):
j -= 1
res += j
return res
def check(X: int) -> bool:
res = count_pairs_less_price(tops_sort, bottoms_sort, X)
for k in range(1, K + 1):
res += count_pairs_less_price(color_tops[k], color_bottoms[k], X + S[k])
res -= count_pairs_less_price(color_tops[k], color_bottoms[k], X)
return res >= P
X = General_Binary_Increase_Search_Integer(0, 3 * 10 ** 9, check)
# Section II: 価格がちょうど X である組み合わせを求める
bottom_price_count = {}
for bottom in bottoms:
bottom_price_count[bottom.price] = bottom_price_count.get(bottom.price, 0) + 1
for k in range(1, K + 1):
# Case A: 同じ色同士のペア
color_bottoms_price_set = set(bottom.price for bottom in color_bottoms[k])
for top in color_tops[k]:
if (y := ((X + S[k]) - top.price)) in color_bottoms_price_set:
for bottom in color_bottoms[k]:
if bottom.price == y:
break
return top.id, bottom.id
# Case B: 異なる色通しのペア
# 色 k のカウントを除く
for bottom in color_bottoms[k]:
bottom_price_count[bottom.price] -= 1
for top in color_tops[k]:
if bottom_price_count.get(X - top.price, 0) == 0:
continue
for bottom in bottoms:
if (top.price + bottom.price == X) and (top.color != bottom.color):
return top.id, bottom.id
# 色 k のカウントを復活
for bottom in color_bottoms[k]:
bottom_price_count[bottom.price] += 1
#==================================================
import sys
input = sys.stdin.readline
write = sys.stdout.write
T = int(input())
write("\n".join(map(lambda ans: f"{ans[0]} {ans[1]}", [solve() for _ in range(T)])))
Kazun