ABC306の振り返り(B, C, D, E)
振り返りです。
import sys from io import StringIO input = lambda: sys.stdin.readline()[:-1] def test(f, data, detail=True): stdin = sys.stdin stdout = sys.stdout sys.stdin = StringIO(data["in"]) out = StringIO() sys.stdout = out err = None try: f() except BaseException as e: err = e else: ans = out.getvalue() exp = data["out"] sys.stdin = stdin sys.stdout = stdout if err: raise err result = "AC" if exp == ans else "WA" print(f"{result}: expected: {exp if detail else ''}, output: {ans if detail else ''}") def test_all(f): for i, data in enumerate(eval(f'test_data{f.__name__[0]}'), 1): print(f"case {i}") test(f, data)B - Base 2
やってみよう!
B
関数を完成させて「Run」ボタンをクリックしよう!
自由欄
コンテスト中
2進数から10進数変換。
コンテスト中は素朴にこんな感じ
結果:#42323982
自由欄
振り返り
int()
で一発でしたね。。
結果:#43665287
自由欄
他の人の提出を見る
わざわざスペースをreplace
する必要もないのか…!
C - Centers
やってみよう!
C
関数を完成させて「Run」ボタンをクリックしよう!
自由欄
コンテスト中
こんな感じ。
num_idx
にインデックスをappendするのは走査順なので、最終的に1~Nのインデックス配列の2つ目の要素が真ん中のインデックスということですね。
結果:#42335811
自由欄
D - Poisonous Full-Course
やってみよう!
D
関数を完成させて「Run」ボタンをクリックしよう!
自由欄
コンテスト中
こんな感じ。
単純なDPです。
結果:#42347396
自由欄
E - Best Performances
やってみよう!
E
関数を完成させて「Run」ボタンをクリックしよう!
自由欄
振り返り
ついでのE問題。
とりあえず愚直に二分探索でソート済み配列を更新するような実装にしてみたら、案の定というかTLEとなりました...(これとかこれとかこれ)
→多分削除は高速でも追加でダメなんだろうなぁ😩
という訳で解説で使われているmultiset
のPython代替を調べます。
下記サイトのアイディアを参考にheapq
+ dict
で削除機能付きのheapqラッパー(my_heapq
)を作って無事ACとなりました。(存在確認機能の実装は割愛。代わりに降順で値を持てるようにしたよ。)
Pythonでmultisetの代用ができるデータ構造 - Tsuboの競プロブログ
なお代替案としてBITを使う方法もあるようですが、今回は値の範囲が$0 \le Y_i \le 10^9$で先読みもできないので不可となります。
from heapq import * from collections import defaultdict class my_heapq: def __init__(self, a, reverse=False): self.reverse = reverse if reverse: a = [-v for v in a] self.a = a heapify(self.a) self.rm_list = defaultdict(int) def heappush(self, item): if self.reverse: item *= -1 heappush(self.a, item) def heappop(self): x = heappop(self.a) while self.rm_list[x]: self.rm_list[x] -= 1 x = heappop(self.a) if self.reverse: x *= -1 return x def heappushpop(self, item): if self.reverse: return -heappushpop(self.a, -item) else: return heappushpop(self.a, item) def rm(self, item): if self.reverse: item *= -1 self.rm_list[item] += 1 def get_first(self): while self.rm_list[self.a[0]]: self.rm_list[self.a[0]] -= 1 heappop(self.a) if self.reverse: return -self.a[0] else: return self.a[0] def E(): N, K, Q = map(int, input().split()) A = [0] * (N + 1) top_k = my_heapq([0] * K) # 通常heap: 先頭が最小 others = my_heapq([0] * (N - K), reverse=True) # 降順heap: 先頭が最大 ans = 0 if N == K: for _ in range(Q): x, y = map(int, input().split()) now = A[x] ans -= now ans += y A[x] = y print(ans) return for _ in range(Q): x, y = map(int, input().split()) now = A[x] A[x] = y if now >= top_k.get_first(): top_k.rm(now) if y >= others.get_first(): # top_kにいて、残る ans -= now ans += y top_k.heappush(y) else: # top_kにいて、外れる ans -= now new = others.heappop() ans += new top_k.heappush(new) others.heappush(y) else: others.rm(now) if y > top_k.get_first(): # top_kにおらず、入る old = top_k.heappop() ans -= old others.heappush(old) ans += y top_k.heappush(y) else: # top_kにおらず、入らない others.heappush(y) print(ans) test_all(E)結果:#43688460
自由欄