AtCoder AGC006 B - Median Pyramid Easy
irisruneです。ABC-F問題の壁は厚いですね。
問題
順列をどのように構築すればよいかがわかれば、順列が存在し得るかどうかも自然とわかります。あるいは小規模なケースで試してみるのもよさそうです。
package main import ( "bufio" "fmt" "os" "strconv" ) var sc *bufio.Scanner func nextInt() int { sc.Scan() i, e := strconv.Atoi(sc.Text()) if e != nil { panic(e) } return i } func main() { sc = bufio.NewScanner(os.Stdin) sc.Split(bufio.ScanWords) n, x := nextInt(), nextInt() if x <= 1 || x >= 2*n-1 { fmt.Println("No") return } values := make([]int, 0) for v := 2; v < 2*n-1; v++ { if v != x { values = append(values, v) } } fmt.Println("Yes") for i := 0; i < 2*n-1; i++ { switch { case i == n-2: fmt.Println(x) case i == n-1: switch { case x < n: fmt.Println(1) default: fmt.Println(2*n - 1) } case i == n: switch { case x < n: fmt.Println(2*n - 1) default: fmt.Println(1) } default: fmt.Println(values[0]) values = values[1:] } } }
直感的に考えると、段目では最小・最大の数()が存在せず、段目ではが存在せず、…といった具合で最終的に段目にはしか存在し得ないように思えます。
とはいえそうはならないだろうということも直感的に想像できると思います。例えばで3段目がの場合には段目の時点でが存在しません。このとき、段目はとなるので段目はとなります。
ここで先の例について考えると、段目で同じ数が2回(連続で)現れるように構成するとその数が段目になるということがわかります。同様に考えると、段目の中央3か所のうち連続する2か所に同じ数が現れる場合段目の中央3か所のうち連続する2か所に同じ数が現れることがわかります。
つまり段目の中央3か所のうち連続する2か所にが現れるよう順列を構成すれば段目にが入ります。またそのような構成はに対して存在するため、を除く場合について順列を構成することができます。
順列の構成方法は様々だと思いますが、上記コードでは以下のようなアルゴリズムで実装しています。
- 中央の3か所以外はを左から順番に入れる。
- 中央の3か所のうち左側はを入れる。残り2か所は以下のように入れる。
- ならば中央に、右側にを入れる。
- ならば中央に、右側にを入れる。
なおのときはどのように配置しても段目にが入るので、上記のアルゴリズムをそのまま用いることができます。
雑記
- Difficulty1552ですが800点問題が解けました。おそらく来週金曜の記事にすると思います。