ABC196 参加記録
- 3完2ペナ 25分でした
A - Difference Max
与えられた と の範囲で を計算する全探索を行って、その最大値が答えです。
B - Round Down
文字列で入力を受け取ります。
python の場合, string.find('.')
で、小数点が含まれていればその位置を、含まれていないなら -1 が返るので、その値を使えば元の数字を簡単に切り取ることができます。
C - Doubled
読み違えて、134431
のように回文になる必要があると思い込んでしまい、2WA。
が までありますが、偶数桁の制限があるので、片側の 〜 を全探索します。 片側を作り、もう一回繰り返した数字が 以下かどうかチェックすれば OK です。
D - Hanjo
探索の仕方が明確にならず、実装に落とせませんでした。 10分ほど考えてスキップし、コンテスト中解くことができませんでした。
コンテスト時の考察では1通りを見つけて回転させるなどすることを考えていましたが、ややこしいですね。 なるべくシンプルに考えられるようになりたいものです。
敷き詰める畳は3種類、、、 です。 これらをDFSを使って実際に敷き詰めていくことで、何通りかを求めることができます。
具体的には、次のようなDFSを行います。
入力
今の座標を受け取ります
処理
がすでに畳のときは次のにいきます。
( が外にはみ出る場合は を渡します。)
そうでないときは、順に3種類の畳を敷き詰めます。
ポイントは、DFSが戻ってきたときに、畳を元に戻すことです。
畳を全て使い切ったときに答えのカウンターを増やします。
抜粋ですが、以下のような処理を3種類の畳全てに行います。 同じような処理を複数書いているので全体のコードは若干見にくいですが、これでACできます。
# 1*1 を配置する if B > 0: field[h][w] = '#' B -= 1 # はみ出したら次の行に行く if w+1 == W: if h+1 == H: # カウントして何もしない ans += 1 else: # 次の行 dfs(h+1, 0) else: dfs(h, w+1) # 元に戻す field[h][w] = '.' B += 1
※ 追記 関数の最初にはみ出た場合の処理を書いておけば、引数を渡すときにはみ出たまま渡すことができるのでスマートに書けます。
E - Filters
と の値を考えてみると、 の条件によって値が確定する場合があることがわかります。 だけであれば状況をまとめられそうだったのですが、加算処理の扱いがわからず本番では解けませんでした。
とっかかりは掴めていたので、あとは加算処理をうまく扱って対応します。
まず、 と の図を書いてみると、以下のようになります。
このグラフからわかる通り、 は最小値を にし、 は最大値を にします。 では、 などはどうなるんだという話ですが、次のように考えると、求めることができます。
とすると、
- のとき、
- のとき、
- のとき、
とすると、同じように場合分けして計算してみると、
となります。図にすると以下のような二つの形にしかならないことがわかります。
同様に考えてみると、 もほぼ同じ挙動をすることがわかります。 ゆえに、 と に関しては、最大の値と最小の値を更新していけばよく、更新の途中で定数関数になったら、それ以降ずっと定数関数になります。
次に加算処理は 軸方向の平行移動とみなせます。グラフを平行移動させてしまうと先程考えた式から変わってしまうので、今回はグラフを移動させるのではなく、次以降の比較対象 の値から を引いてしまいます。そして、実際に求めるのは、グラフを平行移動させた方なので、最後に引いた分を元に戻して答えにします。
最終的なコードは以下になりました。
提出コード
import sys input = sys.stdin.readline def main(): N = int(input()) # 最大値と最小値 higha = float('inf'); lowa = -float('inf') # 加算処理用 cost = 0 # 定数関数になったら flag が True になる flag = False for _ in range(N): a, t = map(int, input().split()) if t == 1: # 加算する処理 cost += a elif t == 2: # 最小値側の更新 lowa = max(a-cost, lowa) if lowa > higha or flag: higha = lowa flag = True else: # 最大値側の更新 higha = min(a-cost, higha) if lowa > higha or flag: lowa = higha flag = True Q = int(input()) X = list(map(int, input().split())) # 加算処理で引いた分を足して答えにする for x in X: if x < lowa: print(lowa + cost) elif lowa <= x <= higha: print(x + cost) else: print(higha + cost) if __name__ == "__main__": main()