[ABC308E] MEX
简单的计数题。
从左到右一遍扫过去,分三种情况:
-
$S_i=M$
维护 $0,1,2$ 三种权值分别出现的次数。第 $i$ 种值的出现次数记为 $c_i$。
-
$S_i=E$
利用第 $1$ 种情况维护的东西去维护两个数组合的所有情况。
记 $t_{a,b}$ 为
M
和E
位置上分别是 $a,b$ 的方案数。有 $t_{a,b}=c_a \times c_b$。 -
$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;
}