ABC 122-C GeT AC (Kotlin)
irisruneです。先週のAGCはA問題早解きで1300出ないらしいしABCはD問題が難しすぎるし過酷ですね…
この問題は数列の部分和を求める問題と(ほぼ)等価です。つまり典型問題ですね。
あらかじめ数列(文字列)の先頭から各インデックスまでの累積和(解)を求めておくことで、
個のクエリそれぞれに対して解を
時間で求めることができます。
fun main(args: Array<String>){
val(n, q) = readLine()!!.split(" ").map(String::toInt)
val s = readLine()!!
val cumSum = mutableListOf(0)
for(i in 1..(n - 1)){
if(s.substring(i - 1, i + 1) == "AC") cumSum.add(cumSum[i - 1] + 1)
else cumSum.add(cumSum[i - 1])
}
for(i in 1..q){
val(l, r) = readLine()!!.split(" ").map(String::toInt)
println(
when {
l == 1 -> cumSum[r - 1]
s.substring(l - 2, l) == "AC" -> cumSum[r - 1] - cumSum[l - 2] - 1
else -> cumSum[r - 1] - cumSum[l - 2]
}
)
}
}
結論から言えば解説と同様に
println(cumSum[r - 1] - cumSum[l - 2])
で出力部分は事足ります。
今回一番悩んだのはこの部分で、累積和の差から解を求める際に左側の区切り位置がちょうど"AC"の間だった場合 1を引く必要があると考えた結果、上記のように出力部分が複雑になってしまいました。
実際は2文字セットで解を求めていく関係上、累積和のインデックスがズレるようです? まだ今一つ理解しきれていません。
今回のコードレビューは特筆するほどでもないですが、
- 累積和を求める部分のif文でKotlin記法を用いて簡略化できる。
- 出力部分のようにwhen文に置き換えることもできる(やってみると余計読みにくいという感想)。
雑記
- AGC032-Aについてはおそらく糸口は掴めているので近いうちに。
- ABC122-Dについては正直に言って解法がわかりません。愚直に場合の数を求めるのはほぼ不可能ですよね…