[ABC308E] MEX

简单的计数题。

从左到右一遍扫过去,分三种情况:

  1. $S_i=M$

    维护 $0,1,2$ 三种权值分别出现的次数。第 $i$ 种值的出现次数记为 $c_i$。

  2. $S_i=E$

    利用第 $1$ 种情况维护的东西去维护两个数组合的所有情况。

    记 $t_{a,b}$ 为 ME 位置上分别是 $a,b$ 的方案数。有 $t_{a,b}=c_a \times c_b$。

  3. $S_i=X$

    利用第 $2$ 种情况统计答案——对于所有的两个数组合都把 $A_i$ 代进去求 $\text{MEX}$,然后别忘乘上两个数组合的方案数。

实现起来不难。

#include <bits/stdc++.h>
#define int long long
#define L(i, a, b) for(int i = (a); i <= (b); i++)
#define R(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 2e5 + 10;
int n, ans, a[N], c[3], t[3][3];
char s[N];
int mex(int a, int b, int c){
    int cnt[4] = {0}; cnt[a] = 1, cnt[b] = 1, cnt[c] = 1;
    L(i, 0, 3) if(!cnt[i]) return i;
}
signed main(){
    scanf("%lld", &n);
    L(i, 1, n) scanf("%lld", &a[i]);
    L(i, 1, n) scanf(" %c", &s[i]);
    L(i, 1, n){
        if(s[i] == 'M'){
            c[a[i]]++;
        }
        else if(s[i] == 'E'){
            L(j, 0, 2) if(c[j]) t[min(j, a[i])][max(j, a[i])] += c[j];
        }
        else{
            L(j, 0, 2) L(k, j, 2){
                if(a[i] < j) ans += t[j][k] * mex(a[i], j, k);
                else if(a[i] >= k) ans += t[j][k] * mex(j, k, a[i]);
                else ans += t[j][k] * mex(j, a[i], k);
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}
posted @ 2023-07-03 18:11  徐子洋  阅读(17)  评论(0)    收藏  举报  来源