なるほど。このあたりから、問題文どおりに素直に探索するようなコーディングでは、時間切れになるのか。 その前に、言語選択を間違えたり、&& を || と書き間違えたりしてミス連発したりしたんだけど。
ということで、一回全部数えておいて再利用することで、問題の規模を N*M から 1*M に減らすとゆー基本ぱたんに遭遇。
C++ は楽でいいなぁ。C だったら int a[n+1]; のとこめんどくさそう(感想)。
#include <bits/stdc++.h> using namespace std; int main() { int n, q; cin >> n >> q; string s; cin >> s; int a[n+1]; a[0] = 0; int ct = 0; for (int i = 0; i < n - 1; i++){ if (s[i]=='A' && s[i+1] == 'C'){ ct++; } a[i+1] = ct; } for (int i = 0; i < q; i++){ int l, r; cin >> l >> r; int ans = a[r-1] - a[l-1]; cout << ans << endl; } }
工夫したのは、端の処理を単純化するための、ダミーの a[0]=0 くらいですかね。あと、右端もマイナス1するのは要注意(これは事前の数え方による)。
とりあえず、C++ 版と同じように書いてみる。cin の代わりになるようなユーティリティ関数を用意していくことになるんだなぁ。
using System; using System.Linq; using static System.Console; class AtCoder { public static void Main() { var t = ReadIntArray(); int n = t[0]; int q = t[1]; var s = ReadLine(); var a = new int[n]; a[0] = 0; int ct = 0; for (int i = 0; i < n - 1; i++){ if (s[i] == 'A' && s[i+1] == 'C'){ ct++; } a[i+1] = ct; } for (int i = 0; i < q; i++){ var x = ReadIntArray(); int l = x[0]; int r = x[1]; WriteLine(a[r-1] - a[l-1]); } } static int[] ReadIntArray() { return ReadLine().Split().Select(x => int.Parse(x)).ToArray(); } }
とりあえず、これでいいと思うんだけど、cobalt1024 さんのやつ がちょっと気になる。 もうちょっと C# に慣れたら見直してみよう。
cunitac さんのやつがいいなと思いながら、自分で書いてみる(かなり影響されてしまった)。
import Control.Monad import Data.Vector.Unboxed ((!)) import qualified Data.Vector.Unboxed as V main = do [_, q] <- map read.words <$> getLine s <- getLine let memo = V.fromList $ f (0::Int) s f n [] = [n] f n ('A':'C':cs) = n:n:f (n+1) cs f n (c:cs) = n:f n cs solve 0 = return () solve q = do [l, r] <- map read.words <$> getLine print (memo!r - memo!l) solve (q-1) solve q
ああ、そうか。メモをこうやってつくれば、使うときに添え字ずらさなくていいのね。