首先,我们可以遍历字符串S,记录每个位置上的M、E、X的个数,分别记为cntM、cntE、cntX。

然后,我们可以通过前缀和的方式计算出每个位置前面M、E、X的个数的累加和,分别记为sumM、sumE、sumX。具体地,我们可以定义三个数组prefixSumM、prefixSumE、prefixSumX,其中prefixSumM[i]表示从位置1到位置i的M的个数,prefixSumE[i]表示从位置1到位置i的E的个数,prefixSumX[i]表示从位置1到位置i的X的个数。则有:

prefixSumM[i] = prefixSumM[i-1] + (S[i] == 'M' ? 1 : 0) prefixSumE[i] = prefixSumE[i-1] + (S[i] == 'E' ? 1 : 0) prefixSumX[i] = prefixSumX[i-1] + (S[i] == 'X' ? 1 : 0)

接下来,我们可以使用两个指针j和k来遍历所有可能的(j,k)组合,其中j表示序列A中第一个数的位置,k表示序列A中第二个数的位置。初始时,j=1,k=2。

我们可以根据j和k的位置,以及前面计算得到的cntM、cntE、cntX、sumM、sumE、sumX数组来计算mex(Aj,Ak)的值。具体地,我们可以根据Ai的取值来判断Ai属于哪个集合,进而计算出mex(Aj,Ak)的值。具体的计算方式如下:

如果Sj = 'M',则Aj属于集合M,mex(Aj,Ak)的值为sumE[k-1] - sumE[j]。 如果Sj = 'E',则Aj属于集合E,mex(Aj,Ak)的值为sumX[k-1] - sumX[j]。 如果Sj = 'X',则Aj属于集合X,mex(Aj,Ak)的值为cntM - sumM[k-1] + sumM[j]。

根据上述的计算方式,我们可以得到mex(Aj,Ak)的值。

然后,我们可以根据mex(Aj,Ak)的值来计算满足SiSjSk=MEX的整数元组(i,j,k)的mex(Ai,Aj,Ak)的和。具体地,我们可以根据Si的取值来判断Si属于哪个集合,进而计算出mex(Ai,Aj,Ak)的和。具体的计算方式如下:

如果Si = 'M',则Ai属于集合M,计算mex(Ai,Aj,Ak)的和时,只需要考虑mex(Aj,Ak)的值小于Ai的情况,即计算sumE[k-1] - sumE[j]。 如果Si = 'E',则Ai属于集合E,计算mex(Ai,Aj,Ak)的和时,需要考虑mex(Aj,Ak)的值小于Ai的情况和mex(Aj,Ak)的值等于Ai的情况,即计算sumX[k-1] - sumX[j] + cntM - sumM[k-1] + sumM[j]。 如果Si = 'X',则Ai属于集合X,计算mex(Ai,Aj,Ak)的和时,只需要考虑mex(Aj,Ak)的值大于Ai的情况,即计算cntM - sumM[k-1] + sumM[j]。

最后,我们可以将计算得到的所有mex(Ai,Aj,Ak)的和进行累加,得到最终的结果。

整体的时间复杂度为O(nlogn)。具体的实现如下:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int N;
    cin >> N;
    vector<int> A(N);
    for (int i = 0; i < N; i++) {
        cin >> A[i];
    }
    string S;
    cin >> S;

    int cntM = 0, cntE = 0, cntX = 0;
    for (int i = 0; i < N; i++) {
        if (S[i] == 'M') {
            cntM++;
        } else if (S[i] == 'E') {
            cntE++;
        } else if (S[i] == 'X') {
            cntX++;
        }
    }

    vector<int> prefixSumM(N), prefixSumE(N), prefixSumX(N);
    prefixSumM[0] = (S[0] == 'M' ? 1 : 0);
    prefixSumE[0] = (S[0] == 'E' ? 1 : 0);
    prefixSumX[0] = (S[0] == 'X' ? 1 : 0);
    for (int i = 1; i < N; i++) {
        prefixSumM[i] = prefixSumM[i-1] + (S[i] == 'M' ? 1 : 0);
        prefixSumE[i] = prefixSumE[i-1] + (S[i] == 'E' ? 1 : 0);
        prefixSumX[i] = prefixSumX[i-1] + (S[i] == 'X' ? 1 : 0);
    }

    int sum = 0;
    int j = 0, k = 1;
    while (k < N) {
        int mexAjAk;
        if (S[j] == 'M') {
            mexAjAk = prefixSumE[k-1] - (j > 0 ? prefixSumE[j-1] : 0);
        } else if (S[j] == 'E') {
            mexAjAk = prefixSumX[k-1] - (j > 0 ? prefixSumX[j-1] : 0) + cntM - prefixSumM[k-1] + (j > 0 ? prefixSumM[j-1] : 0);
        } else if (S[j] == 'X') {
            mexAjAk = cntM - prefixSumM[k-1] + (j > 0 ? prefixSumM[j-1] : 0);
        }

        if (S[k] == 'M') {
            if (mexAjAk < A[k]) {
                sum += mexAjAk;
            }
        } else if (S[k] == 'E') {
            if (mexAjAk < A[k]) {
                sum += mexAjAk;
            } else if (mexAjAk == A[k]) {
                sum += mexAjAk + cntM - prefixSumM[k-1] + (j > 0 ? prefixSumM[j-1] : 0);
            }
        } else if (S[k] == 'X') {
            if (mexAjAk > A[k]) {
                sum += cntM - prefixSumM[k-1] + (j > 0 ? prefixSumM[j-1] : 0);
            }
        }

        j++;
        if (j == k) {
            k++;
        }
    }

    cout << sum << endl;

    return 0;
}

以上为时间复杂度为O(nlogn)的C++实现

给定一个长度为N的序列A=A1A2…AN其中Ai∈012以及一个长度为N的字符串S=S1S2…SN其中Si∈MEX。找到所有满足1≤ijk≤N且SiSjSk=MEX的整数元组ijk的mexAiAjAk的和。这里mexAiAjAk表示最小的非负整数它既不等于AiAj也不等于Ak。用时间复杂度Onlogn和C++实现

原文地址: https://www.cveoy.top/t/topic/hFxv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录