あるエンジニアのAtCoder奮闘記

東京都港区にあるアミフィアブル株式会社のエンジニアが、AtCoderで解いた問題について振り返ったりしていく会社公認のブログです。

AtCoder AGC006 B - Median Pyramid Easy

irisruneです。ABC-F問題の壁は厚いですね。

問題

atcoder.jp

順列をどのように構築すればよいかがわかれば、順列が存在し得るかどうかも自然とわかります。あるいは小規模なケースで試してみるのもよさそうです。

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:]
        }
    }
}

直感的に考えると、N-1段目では最小・最大の数(1,2N-1)が存在せず、N-2段目では2,2N-2が存在せず、…といった具合で最終的に1段目にはNしか存在し得ないように思えます。

とはいえそうはならないだろうということも直感的に想像できると思います。例えばN=3で3段目が3,2,1,4,5の場合には2段目の時点で3が存在しません。このとき、2段目は2,2,4となるので1段目は2となります。

ここで先の例について考えると、2段目で同じ数が2回(連続で)現れるように構成するとその数が1段目になるということがわかります。同様に考えると、K+1段目の中央3か所のうち連続する2か所に同じ数が現れる場合K(\gt1)段目の中央3か所のうち連続する2か所に同じ数が現れることがわかります。

つまりN-1段目の中央3か所のうち連続する2か所にxが現れるよう順列を構成すれば1段目にxが入ります。またそのような構成はx=2,3,\ldots,2N-2に対して存在するため、x=1,2N-1を除く場合について順列を構成することができます。

順列の構成方法は様々だと思いますが、上記コードでは以下のようなアルゴリズムで実装しています。

  1. 中央の3か所以外は2,3,\ldots,x-1,x+1,\ldots,2N-2を左から順番に入れる。
  2. 中央の3か所のうち左側はxを入れる。残り2か所は以下のように入れる。
    1. x\lt Nならば中央に1、右側に2N-1を入れる。
    2. x\geq Nならば中央に2N-1、右側に1を入れる。

なおN=2のときはどのように配置しても1段目に2が入るので、上記のアルゴリズムをそのまま用いることができます。

雑記

  • Difficulty1552ですが800点問題が解けました。おそらく来週金曜の記事にすると思います。