👻

AtCoder Beginner Contest 372参加記

2024/09/22に公開

ユニークビジョンプログラミングコンテスト2024 秋(AtCoder Beginner Contest 372)に参加したので記録を残します。
https://atcoder.jp/contests/abc372

Rated参加は二ヶ月半ぶりくらいでした。灰パフォも覚悟したけど、とりあえず3完はできました。

A - delete .

replaceを使って.を削除して出力です。

fun main() {
    val s = readln()
    println(s.replace(".", ""))
}

https://atcoder.jp/contests/abc372/submissions/57949668

B - 3^A

ちょっと難しめですね。固定でM個の0を出力でいいのではと思ったのですが、Nに制約があるのでそれだとダメでした。

3^0から3^{10}までを事前に計算しておいて、大きいほうを優先してMから割っていって、その時の指数を答えに追加していきます。指数は商の個数分追加です。商が0なら追加しません。

import kotlin.math.pow

fun main() {
    var m = readln().toInt()
    val list = (0..10).map { it to 3.0.pow(it).toInt() }
        .reversed()

    val ans = mutableListOf<Int>()

    for((p, num) in list) {
        val div = m / num

        if(div == 0) {
            continue
        }
        repeat(div) {
            ans.add(p)
        }
        m -= num * div
    }
    println(ans.size)
    println(ans.joinToString(" "))
}

https://atcoder.jp/contests/abc372/submissions/57962018

C - Count ABC Again

これもちょっと悩んでしまいました。そんなに難しくはないはずなのですが…

クエリの回数分の処理を実行しないといけないのは確定なので、部分文字列が何個含まれているかの判定を高速化する必要があります。置き換え自体はO(1)でできます。

基本的には個数は事前に数えておいて、クエリごとにそれが変化するかどうかだけを判定して答えを増減します。ABCが3文字なので、クエリで置き換える周辺の数マスだけ調べることで高速化できます。

範囲で考えると混乱するので、クエリによって影響する範囲の開始位置だけに注目すると、X_i - 2からX_iまでの3箇所を調べればいいです。各開始位置から+2マスまでを調べます。

添え字の計算時に範囲外にならないように考慮が必要です。(この考慮が不十分で1ペナ)

import java.io.PrintWriter

fun main() {
    val (n, q) = readln().split(" ").map { it.toInt() }
    val s = readln()
    val xc = List(q) {
        val (x, c) = readln().split(" ")
        x.toInt() to c.first()
    }

    val sList = (listOf('.') + s.toList()).toMutableList()
    var ans = count(s)

    val out = PrintWriter(System.out)

    for((xi, ci) in xc) {
        for(i in xi - 2..xi) {
            if(i < 0) {
                continue
            }
            if(i > n - 2) {
                continue
            }

            if(sList[i] == 'A' && sList[i+1] == 'B' && sList[i+2] == 'C') {
                ans--
            }
        }

        sList[xi] = ci

        for(i in xi - 2..xi) {
            if(i < 0) {
                continue
            }
            if(i > n - 2) {
                continue
            }

            if(sList[i] == 'A' && sList[i+1] == 'B' && sList[i+2] == 'C') {
                ans++
            }
        }
        out.println(ans)
    }
    out.flush()
}

fun count(s: String): Int {
    var count = 0
    var index = 0
    while (true) {
        val ri = s.indexOf("ABC", index)
        if(ri == -1) {
            break
        }

        count++
        index = ri + 1
    }

    return count
}

https://atcoder.jp/contests/abc372/submissions/57978370

D - Buildings

全然わからず。制約をよく見ると高さは重複がなくて全てN以下の数、つまり1からNまでの短調増加列の並び替えなので、それを利用するのだろうとは思いましたが解けず。

感想

モチベが消失しかけていましたが、やっぱり競プロのコンテストに参加するのは自分にとって大事な習慣だったなと思い直して思い切って参加してみました。競技としてというより、コードを日常的に書く習慣として良いなと。それが目的だったのにいつの間にかレートを上げるのが目的となっていて、よくなかったなと。それでうまくいっているうちはいいのですが、うまくいかなくなった時にレートを気にして参加をするのが怖くなって、参加しなくなって… ということになっていました。

レートを一切気にしないというのは現実的には無理だと思いましたが、レートを過剰に気にして参加しなくなるというのは本末転倒でしたね。今後はレートが下がっていくとしてモチベを保つにはどうするかあれこれ模索していくことになりそうです。とにかく参加をやめないことを優先して考えていきたいです。まあそれに失敗した結果が二ヶ月半の空白なんですけどね。なかなか道は険しい…

Discussion