Problem:
Score : 600 points

Problem Statement

In Dwango Co., Ltd., there is a content distribution system named 'Dwango Media Cluster', and it is called 'DMC' for short.

The name 'DMC' sounds cool for Niwango-kun, so he starts to define DMC-ness of a string.

Given a string S of length N and an integer k (k \geq 3),
he defines the k-DMC number of S as the number of triples (a, b, c) of integers that satisfy the following conditions:

0 \leq a < b < c \leq N - 1

S[a] = D

S[b] = M

S[c] = C

c-a < k

Here S[a] is the a-th character of the string S. Indexing is zero-based, that is, 0 \leq a \leq N - 1 holds.

For a string S and Q integers k_0, k_1, ..., k_{Q-1}, calculate the k_i-DMC number of S for each i (0 \leq i \leq Q-1).

Constraints

3 \leq N \leq 10^6

S consists of uppercase English letters

1 \leq Q \leq 75

3 \leq k_i \leq N

All numbers given in input are integers

Input

Input is given from Standard Input in the following format:

N
S
Q
k_{0} k_{1} ... k_{Q-1}

Output

Print Q lines.
The i-th line should contain the k_i-DMC number of the string S.

Sample Input 1

18
DWANGOMEDIACLUSTER
1
18

Sample Output 1

1

(a,b,c) = (0, 6, 11) satisfies the conditions.

Strangely, Dwango Media Cluster does not have so much DMC-ness by his definition.

Sample Input 2

18
DDDDDDMMMMMCCCCCCC
1
18

Sample Output 2

210

The number of triples can be calculated as 6\times 5\times 7.

Sample Input 3

54
DIALUPWIDEAREANETWORKGAMINGOPERATIONCORPORATIONLIMITED
3
20 30 40

Sample Output 3

0
1
2

(a, b, c) = (0, 23, 36), (8, 23, 36) satisfy the conditions except the last one, namely, c-a < k_i.

By the way, DWANGO is an acronym for "Dial-up Wide Area Network Gaming Operation".

Sample Output 4

30
DMCDMCDMCDMCDMCDMCDMCDMCDMCDMC
4
5 10 15 20

Sample Output 4

10
52
110
140

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using static System.Math;

class P
{
    static void Main()
    {
        int n = int.Parse(Console.ReadLine());
        string s = Console.ReadLine();
        Console.ReadLine();
        int[] q = Console.ReadLine().Split().Select(int.Parse).ToArray();
        //D,M,Q,Xに文字を分類し、WMに突っ込む
        int[] ruisekiD = new int[n + 1];
        int[] ruisekiM = new int[n + 1];
        int[] ruisekiC = new int[n + 1];
        List<int> posD = new List<int>();
        List<int> posM = new List<int>();
        List<int> posC = new List<int>();
        for (int i = 0; i < s.Length; i++)
        {
            switch (s[i])
            {
                case 'D':
                    ruisekiD[i + 1] = ruisekiD[i] + 1;
                    ruisekiM[i + 1] = ruisekiM[i];
                    ruisekiC[i + 1] = ruisekiC[i];
                    posD.Add(i);
                    break;
                case 'M':
                    ruisekiD[i + 1] = ruisekiD[i];
                    ruisekiM[i + 1] = ruisekiM[i] + 1;
                    ruisekiC[i + 1] = ruisekiC[i];
                    posM.Add(i);
                    break;
                case 'C':
                    ruisekiD[i + 1] = ruisekiD[i];
                    ruisekiM[i + 1] = ruisekiM[i];
                    ruisekiC[i + 1] = ruisekiC[i] + 1;
                    posC.Add(i);
                    break;
                default:
                    ruisekiD[i + 1] = ruisekiD[i];
                    ruisekiM[i + 1] = ruisekiM[i];
                    ruisekiC[i + 1] = ruisekiC[i];
                    break;
            }
        }
        //各クエリ毎に舐めていく際のそれを変える?
        //各クエリ毎にD開始で舐める 末尾削除&先頭追加を繰り返しながら舐めていく
        if(posD.Count == 0 || posM.Count== 0|| posC.Count == 0)
        {
            for (int i = 0; i < q.Length; i++) Console.WriteLine(0);
            return;
        }

        for (int qiter = 0; qiter < q.Length; qiter++)
        {
            int currentQuery = q[qiter];

            //cの現在のそれ
            Stack<int> cInds = new Stack<int>();
            long res = 0;
            //現在のDにおいて該当するCについてつくれるMの数
            long currentmCount = 0;
            //現在の区間において存在しているmの数
            long currensectiontmCount = 0;

            /*int ccount = 0;
            for (int i = currentQuery - 1; i >= 0; i--)
            {
                switch (s[i])
                {
                    case 'M':
                        currensectiontmCount++;
                        currentmCount += ccount;
                        break;
                    case 'C':
                        ccount++;
                        break;
                }
            }
            */
            for (int i = 0; i < currentQuery; i++)
            {
                switch (s[i])
                {
                    case 'M':
                        currensectiontmCount++;
                        break;
                    case 'C':
                        cInds.Push(i + currentQuery);
                        currentmCount += currensectiontmCount;
                        break;
                }
            }
            //区間を一つ移動
            for (int i = posD[0]; i < s.Length - 2; i++)
            {
                switch (s[i])
                {
                    case 'D':
                        res += currentmCount;
                        break;
                    case 'M':
                        currentmCount -= cInds.Count;
                        currensectiontmCount--;
                        break;
                    case 'C':
                        cInds.Pop();
                        break;
                }
                if(i + currentQuery < s.Length)
                {
                    switch (s[i + currentQuery])
                    {
                        case 'D':
                            //ケツにD出てきても何もせんでええやろ
                            break;
                        case 'M':
                            currensectiontmCount++;
                            break;
                        case 'C':
                            cInds.Push(i + currentQuery);
                            currentmCount += currensectiontmCount;
                            break;
                    }
                }
            }
            Console.WriteLine(res);
        }
    }
}