'R','G','B'のみからなる、長さNの文字列Sがあります。
以下の2つの条件をもとに満たす組(i,j,k)(1<=i<=j<=k<=N)の数を求めてください。
要は、各文字が別々かつ、幅が同じではない組み合わせは何通りあるかという問題
愚直に三重for
def d162(n , sli): ans = 0 for i in range(n - 3): for w in range(i + 1 , n): for q in range(w + 1 , n): if sli[i] != sli[w] and sli[i] != sli[q] and sli[w] != sli[q] and w - i != q - w: ans += 1 return ans def main(): n = int(input()) sli = list(str(input())) print(d162(n , sli)) if __name__ == '__main__': main()
->TLEになり不正解
ここで考えてもらいたいのが、三重for目、何をしているかというと
この二つを判定しているわけです。
ならば、R , G , Bそれぞれで出現箇所を把握しておけば、2つ目が確定した以降の残りの数を求めればOK
その為、手順はこんな感じになります
pythonには便利なライブラリbisect君がいるので
活躍してもらいましょう(他言語では累積和で解けます)
import bisect def d162(n , sli): ans = 0 Rli = [] Gli = [] Bli = [] for i in range(n): if sli[i] == "R": Rli.append(i) elif sli[i] == "G": Gli.append(i) else: Bli.append(i) Rcount = len(Rli) Gcount = len(Gli) Bcount = len(Bli) Rli.sort() Gli.sort() Bli.sort() for i in range(n - 3): for w in range(i + 1 , n): if sli[i] != sli[w]: k = "RGB".replace(sli[i] , "").replace(sli[w] , "") if k == "R": ans += Rcount - bisect.bisect_right(Rli , w) elif k == "G": ans += Gcount - bisect.bisect_right(Gli , w) else: ans += Bcount - bisect.bisect_right(Bli , w) if w + w - i < n and sli[w + (w - i)] == k: ans -= 1 return ans def main(): n = int(input()) sli = list(str(input())) print(d162(n , sli)) if __name__ == '__main__': main()