code festival 予選b 解説

71
CODE FESTIVAL 2014 予選B 解説 AtCoder株式会社 代表取締役 高橋 直大 2014/10/26 1

Upload: atcoder-inc

Post on 02-Jul-2015

2.381 views

Category:

Education


0 download

DESCRIPTION

CODE FESTIVAL 予選B 解説

TRANSCRIPT

Page 1: CODE FESTIVAL 予選B 解説

CODE FESTIVAL 2014 予選B解説

AtCoder株式会社 代表取締役

高橋 直大

2014/10/26 1

Page 2: CODE FESTIVAL 予選B 解説

©AtCoder Inc. All rights reserved. 2

A問題 あるピアニスト

2014/10/26 2

Page 3: CODE FESTIVAL 予選B 解説

A問題

• 問題概要

– 2つの整数A,Bが与えられる。

– 大きい方を出力してください。

• 解説

– 比較演算子とif文を使って場合分けする

– 諸言語で予め実装されているmax関数等を使う

2014/10/26 3

Page 4: CODE FESTIVAL 予選B 解説

©AtCoder Inc. All rights reserved. 4

B問題 歩く人

2014/10/26 4

Page 5: CODE FESTIVAL 予選B 解説

B問題 問題概要

• 要素数Nの数列Aが与えられる。

• A[ 1]~A[i]の総和がKを超える最小のiを求めよ。

• 制約

– 1 ≦ N ≦ 100,000

– 1 ≦ A[i] ≦ 100,000

– 1 ≦ K ≦ 1,000,000,000

2014/10/26 5

Page 6: CODE FESTIVAL 予選B 解説

B問題 アルゴリズム

• 毎日、その日までに累計で何歩歩いたか求める。

– 累計歩数を保存しておく別の変数を用意してそれに次々A[i]を足していけば良い。

• 各日について累計K歩を達成できたか求める。

– 簡単なif文

• 初めて累計K歩を達成した日を出力すれば良い。

2014/10/26 6

Page 7: CODE FESTIVAL 予選B 解説

©AtCoder Inc. All rights reserved. 7

C問題 錬金術士

2014/10/26 7

Page 8: CODE FESTIVAL 予選B 解説

C問題 問題概要

• 2N( Nは整数) 文字の文字列S1, S2,S3がある

• S1の半分とS2の半分を取ってきて並び替えることでS3が構成可能か判断せよ。

• 制約

– 2 ≦ 2 N ≦ 100,000

– S1,S2,S3は大文字アルファベットのみから構成される

2014/10/26 8

Page 9: CODE FESTIVAL 予選B 解説

C問題 アルゴリズム

• 構成する際に並び替えることができるので、S1,S2,S3の文字列の順番は答えに影響しない

– 各アルファベットを何個ずつ含むかだけが必要

• まずはN文字ずつ取り出すという制約を無視する

– 取り出し方をアルファベットごとに独立して考えることが出来る

– 例えば「'A'をS1から何個取り出すか」と「'B'をS1から何個取り出すか」は全く影響しあわない

2014/10/26 9

Page 10: CODE FESTIVAL 予選B 解説

C問題 アルゴリズム

• 各アルファベットについてS1から取り出すことが出来る文字数の範囲を求める

• S1から取り出す文字数が少なすぎると、S2から取り出す文字数にかかわらず、S3を構成するのに足りなくなる

– 例:S1='AABB' S2='AAAB' S3='ABBB'のときS1から' B 'を1つしか取り出さないとすると、S3を構成できなくなる

2014/10/26 10

Page 11: CODE FESTIVAL 予選B 解説

C問題 アルゴリズム

• 各アルファベットについてS1から取り出すことが出来る文字数の範囲を求める

• S1から取り出す文字数が多すぎると、S2から取り出す文字数にかかわらず、S3を構成するのに余ってしまう

– 例:S1=‘AAAB’ S2=‘AABB’ S3=‘ABBB’のときS1から‘ A’を3つも取り出すとすると、S3を構成するのに余ってしまう

2014/10/26 11

Page 12: CODE FESTIVAL 予選B 解説

C問題 アルゴリズム

• 各アルファベットについてS1から取り出すことが出来る文字数の範囲を求める

• あるアルファベットがS1,S2,S3にそれぞれC1,C2,C3文字ずつ含まれていたとすると、S1から取り出すこ

とが出来る文字数の範囲は

– max(0, C3-C2) ~ min(C1, C3)

– この間の値は全てとれる

2014/10/26 12

Page 13: CODE FESTIVAL 予選B 解説

C問題 アルゴリズム

• 各アルファベットについてこの範囲をもとめて、うまく総和がN/2にすることが出来るか判断すれば良い

• できるだけ少なくS1から取り出した時の文字数と、できるだけ多くS1から取り出した時の文字数の間にN/2があるかどうか判断する。

– それぞれさきほどの max(0,. C3-C2) ~ min(C1, C3) の総和を取れば求めることが出来る

2014/10/26 13

Page 14: CODE FESTIVAL 予選B 解説

©AtCoder Inc. All rights reserved. 14

D問題 登山家

1. 問題概要

2. アルゴリズム

2014/10/26 14

Page 15: CODE FESTIVAL 予選B 解説

D問題 問題概要

• 要素数Nの数列Aが与えられる。

• 各i( 1≦i≦N)に対してiとjの間の全てのk( jも含む)についてA[k]≦ A[ i]であるようなjの個数を求めよ。

• 制約

– 1≦N≦ 100,000

– 1≦A[i]≦100,000

2014/10/26 15

Page 16: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 図示

2014/10/26 16

Page 17: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

2014/10/26 17

Page 18: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

2014/10/26 18

Page 19: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

• 両端をどう求めるか?

– 全探索

– DP

– stackをつかう

– 二分探索

2014/10/26 19

Page 20: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

• 両端をどう求めるか?

– 全探索

– DP

– stackをつかう

– 二分探索

2014/10/26 20

Page 21: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iがそれより東の山小屋をどこまで見ることが出来るかを求める

– 山小屋iから東向きに順番に調べていき、初めて見えなくなった山小屋の一つ前まで見える

2014/10/26 21

Page 22: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 22

Page 23: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• OK

2014/10/26 23

Page 24: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• OK

2014/10/26 24

Page 25: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• OK

2014/10/26 25

Page 26: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• NG

2014/10/26 26

Page 27: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 3つまで見える

2014/10/26 27

Page 28: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 西側についても同様に求めて最後に足し合わせる

• 各iについてO(N)かかる

– 合計でO(N^2)

– 部分点(30点)が得られる

2014/10/26 28

Page 29: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

• 両端をどう求めるか?

– 全探索

– DP

– stackをつかう

– 二分探索

2014/10/26 29

Page 30: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = 山小屋iの東側で見えない山小屋の中で最も西にあるもの

• 先ほどの例でNGにあたる山小屋

2014/10/26 30

Page 31: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• NG

2014/10/26 31

Page 32: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 東から順番にdp[i]の値を埋めていく

• dp[i] = i+1

• h[dp[i]] > h[i]になるまでdp[i] = dp[dp[i]]という代入をしつづける

2014/10/26 32

Page 33: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 33

Page 34: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 一番東に無限に高いhをもつ番兵をつくると実装しやすい

2014/10/26 34

Page 35: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = i+1から開始

2014/10/26 35

Page 36: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = i+1から開始

2014/10/26 36

Page 37: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 37

Page 38: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = i+1から開始

2014/10/26 38

Page 39: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = i+1から開始

2014/10/26 39

Page 40: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 40

Page 41: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] =i +1から開始

2014/10/26 41

Page 42: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] =i +1から開始

2014/10/26 42

Page 43: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 43

Page 44: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 44

Page 45: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] =i +1から開始

2014/10/26 45

Page 46: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] =i +1から開始

2014/10/26 46

Page 47: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 47

Page 48: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 48

Page 49: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 49

Page 50: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] =i +1から開始

2014/10/26 50

Page 51: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 51

Page 52: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i] ≧ h[dp[i]]なのでdp[i] をdp[dp[ i]]に更新する

2014/10/26 52

Page 53: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = dp[dp[i]]という操作を最悪でO(N)回するので総計算量はO(N^2)?

– 実はO(N)

• dp[i] = dp[dp[i]]という操作(先ほどの例では黒い矢印をたどること)は各矢印についてたかだか1回しか行われない

– 矢印はO(N)個しかないので総計算量はO(N)

• 満点が得られる

2014/10/26 53

Page 54: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• dp[i] = dp[dp[i]]という操作を最悪でO(N)回するので総計算量はO(N^2)?

– 実はO(N)

• dp[i] = dp[dp[i]]という操作(先ほどの例では黒い矢印をたどること)は各矢印についてたかだか1回しか行われない

– 矢印はO(N)個しかないので総計算量はO(N)

• 満点が得られる

2014/10/26 54

Page 55: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

• 両端をどう求めるか?

– 全探索

– DP

– stackをつかう

– 二分探索

2014/10/26 55

Page 56: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• stackを用意する

• 東から順番に

– h[i] が h[ stackの先頭]より大きい限りstackの先頭をpopし続ける

– dp[ i] = stackの先頭

– iをstackの先頭にpushする

• というふうにやると先ほどと同じdp[i]が得られる

• 実質やっていることはDP解と同じ

– こちらのほうがO(N)であることがわかりやすい

2014/10/26 56

Page 57: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 山小屋iから見える範囲

• これはiを含むある区間である

• iに一番近いh[i]より高い山小屋が両端となる

• 両端をどう求めるか?

– 全探索

– DP

– stackをつかう

– 二分探索

2014/10/26 57

Page 58: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• iについて、h[i]より高い山小屋の位置が全てわかっていれば、二分探索(Successor)で見える範囲の両端を求めることが出来る

• 高い順に山小屋を追加していき、毎回二分探索すれば良い

2014/10/26 58

Page 59: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 59

Page 60: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 60

Page 61: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 61

Page 62: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 62

Page 63: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 63

Page 64: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 64

Page 65: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 65

Page 66: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 66

Page 67: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 67

Page 68: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 68

Page 69: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• 例

2014/10/26 69

Page 70: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• h[i]が大きい順にiをset等のデータ構造に追加していく

• 追加する前にiのupper_boundとその前を調べる

• 高さが同じ山小屋が複数あるときは、すべてについて二分探索をした後にsetに追加する

• 総計算量は

– O(NlogN)

2014/10/26 70

Page 71: CODE FESTIVAL 予選B 解説

D問題 アルゴリズム

• この解法を思いつく人が一番多いと予想される

• しかし、挿入と探索が効率的にできるデータ構造を実装するのはコンテスト時間内では慣れていないと難しい

– set等が予め用意されていない言語だと、この解法は実装しづらい

– そういう時は先程のDPやstackを使った解法を実装すれば良い

2014/10/26 71