题解 AT3950 【[AGC022E] Median Replace】
AGC 022E
首先考虑如何判断一个数列是否合法。
考虑维护一个栈,满足从栈顶到栈底是由一段连续的
- 若加入的数为
0 :- 若栈顶为
0 ,如果栈内有2 个0 ,那么可以替换成一个0 ,否则入栈。 - 若栈顶为
1 ,直接入栈即可。
- 若栈顶为
- 若加入的数为
1 :- 若栈顶为
0 ,则新加入的1 可以和栈顶的0 抵消,因为再加入一个数,这三个数的中位数之和新加入的数有关。 - 若栈顶为
1 ,如果栈内只有一个1 则入栈,否则忽略它。
- 若栈顶为
最后只需要判断栈内
不难发现栈中
- 若这一位为?,则将上面两种转都做一遍即可。
时间复杂度为
Code
int n;
int f[MAXN][3][3];
char s[MAXN];
int main(){
scanf("%s",s + 1);
n = strlen(s + 1);
f[0][0][0] = 1;
for(int i = 0;i < n;i++){
if(s[i + 1] != '1'){
for(int a = 0;a <= 2;a++){
addmod(f[i + 1][a][1],f[i][a][2]);
addmod(f[i + 1][a][2],f[i][a][1]);
addmod(f[i + 1][a][1],f[i][a][0]);
}
}
if(s[i + 1] != '0'){
for(int a = 0;a <= 2;a++){
addmod(f[i + 1][a][0],f[i][a][1]);
addmod(f[i + 1][a][1],f[i][a][2]);
}
addmod(f[i + 1][1][0],f[i][0][0]);
addmod(f[i + 1][2][0],f[i][1][0]);
addmod(f[i + 1][2][0],f[i][2][0]);
}
}
int ans = 0;
for(int a = 0;a <= 2;a++){
for(int b = 0;b <= a;b++)
addmod(ans,f[n][a][b]);
}
printf("%d\n",ans);
return 0;
}