ABC001 解説

26
AtCoder Beginner Contest 001 解解 AtCoder 解解解解 解解解解解 解解 解解

description

ABC001です

Transcript of ABC001 解説

Page 1: ABC001 解説

AtCoder Beginner Contest 001解説

AtCoder 株式会社 代表取締役高橋 直大

Page 2: ABC001 解説

コンテストデータ• こちらより入出力のダウンロードが可能

です– http://www.chokudai.info/atcoder/ABC001.rar– 個人サーバーですので、不安定な可能性があ

ります。

Page 3: ABC001 解説

A 問題概要• 整数が 2 つ与えられます。引き算した結果

を求めなさい。– 整数の値は、 0 以上 2000 以下

Page 4: ABC001 解説

A 問題 解説• まず、 2 つの整数を、標準入力から読み取

る– C 言語なら scanf, C++ なら cin など– 解らない場合は、 practice から各言語の例が

参照できます。– http://practice.contest.atcoder.jp/tasks/practice_1

• 読み取った2つの式を引き算• 出てきた値を出力する– こちらもわからない場合は practice から確認

Page 5: ABC001 解説

B 問題概要• 距離を表す整数が与えられる• これを、 VV という単位に変換する– これは、距離によって場合分けで決定される

Page 6: ABC001 解説

B 問題 解説• 整数を読み込んで、場合分け– 0.1km 未満なら~– 5km 未満なら~• 解らない場合は if ~ else 節について調べよう!

• 全て m 単位に揃えてあげると簡単

Page 7: ABC001 解説

C 問題 問題概要• 風程・風向の角度が与えられる• これを、風力、風向 (16 方位 ) に変換しな

さい

Page 8: ABC001 解説

C 問題 解説• やることは、 B 問題と全く同じ!– 風程も風向も、場合分けして変換してあげる

だけ!• でも、 if 文を大量に書くような実装をして

はいけません!– 通るけれども、面倒だし、バグも出やすい

Page 9: ABC001 解説

C 問題 風向きの処理• 16 方位の間隔は全て一定– 全部の if 文を書かずに、繰り返しで処理できる!

• 全ての間隔は 22.5 度間隔なので、 22.5 度ずつ増やして判定する

– もっと簡単に、数式で一発で表すことも可能• ((Dis * 10 + 1125) / 2250) % 16 などの処理で、 0 ~ 15 の

数字に変換できる• N,NNE などの方向を表す文字列は、配列とし

て書いておく– 問題文からコピーして抽出しても良い

Page 10: ABC001 解説

C 問題 風速の処理• 風程を 60 で割ると、風速になる– この割り算の処理が凄く危険!!

• 例えば、風程 201m だと風速 3.35m/s だが、3.35 は風力の境界線上– 誤差で少しでもずれると、間違った判定をし

てしまう。• 3.3499999999999…. だと、風力 2• 3.3500000000000…. だと、風力 3

Page 11: ABC001 解説

C 問題 小数の対策方法• 基準となる風力を、逆に風程に変換する– 風速 3.35m/s 以下 → 風程 201m 以下

• 少しだけ小さい値を足してあげる– 3.499999.. + 0.00001– 3.500000.. + 0.00001– どちらも風力 3 となる• 入力が整数のみだから使える方法なので注意!• 入力間隔が細かいときなどは使えない場合があり

ます

Page 12: ABC001 解説

C 問題 風速の処理• 入力が面倒!– とりあえずコピペして、数字だけ抽出するよ

うなプログラムをさくっと書こう!• それが面倒な人は、手入力や1つずつコピペが早

いと思います。• 英語しか読み込めないテキストエディタで開い

て、 ? を消去、なんて手もあります– 必要な数字を配列に入れてしまえば、繰り返

し判定するだけ!

Page 13: ABC001 解説

D 問題 問題概要• 雨が降った期間が複数与えられる• マージしなさい

Page 14: ABC001 解説

D 問題 前処理• データを丸める– 1357-1457  →  1355-1500

• やり方– まず時間と分を、分だけの単位に変換する• 1時間を 60 分として、 0 時 0 分から何分経ったか、

に変換する– 5 で割った余りに対して、足したり引いたり

を行う

Page 15: ABC001 解説

D 問題 解説• それぞれの間隔において、配列を用意して

あげる

0:00 1:00

Page 16: ABC001 解説

D 問題 解説• それぞれの間隔において、配列を用意して

あげる初期値は全て 0• 入力に対して、その範囲を 1 で塗りつぶす– 例: 0:20 – 0:45

0:00 1:00

Page 17: ABC001 解説

D 問題 解説• それぞれの間隔において、配列を用意して

あげる初期値は全て 0• 入力に対して、その範囲を 1 で塗りつぶす– 例: 0:20 – 0:45 の後追加で、 0:10 – 0:40

0:00 1:00

Page 18: ABC001 解説

D 問題 解説• それぞれの間隔において、配列を用意して

あげる 初期値は全て 0• 入力に対して、その範囲を 1 で塗りつぶす– 例: 0:20 – 0:45 の後追加で、 0:10 – 0:40

• 左から順番に、連続した範囲を調べる0:00 1:0

Page 19: ABC001 解説

D 問題 高速な解法 1

• 入力をソートしよう!

Page 20: ABC001 解説

D 問題 高速な解法 1

• 開始時間が早い順にソートする

Page 21: ABC001 解説

D 問題 高速な解法 1

• ソートしてしまえば、順番に処理してあげれば、範囲を更新出来る。– 例えば、 10:00 – 11:30 の後に、 10:30-12:30 が

来た場合• 10:00-12:30 に更新する

– その後 13:30-14:00 が来た場合• 10:00-12:30 を出力し、 13:30-14:00 をメモリに入れ

る– その後 13:40-13:50 が来た場合• 更新する部分がないので何もしない

Page 22: ABC001 解説

D 問題 高速な解法 2

• 座標を圧縮しよう–事前に境界線を調べておいて、その範囲しか

調べない!

0:00 1:00

0:00 1:00

Page 23: ABC001 解説

D 問題 高速な解法 3

• 通称「いもす法」を使おう!– いままでのやり方

– いもす法(始点に1、終点の 1 個先に -1 を入れる)

0:00 1:00

0:00 1:00

1 -1

Page 24: ABC001 解説

D 問題 高速な解法 3

• 色んな範囲に対して、始点に 1 を足して、終点に -1 を足す、を繰り返す

0 1 1 1 0 1 -1

1:00

-1 0 0 -1 -1

Page 25: ABC001 解説

D 問題 高速な解法 3

• 作った配列に対して、そこまでの足した値を計算してあげる–元の配列

– 足した配列

0 1 1 1 0 1 -1

1:00

-1 0 0 -1 -1

0 1 2 3 0 1 02 2 2 1 0

Page 26: ABC001 解説

D 問題 高速な解法 3

• この配列の、数字が 1 以上になっている範囲が、求める範囲– 入力範囲が増えても、始点と終点だけを入れ

れば良いので、配列すべてをなぞるのは1回だけで良い!

0 1 2 3 0 1 02 2 2 1 0