[AGC022E] Median Replace 题解
题意:
有个长度为 $N$($N$ 为奇数)的 $\texttt{01}$ 串 $s$,其中有若干位置是 $\texttt{?}$。
一次操作可将 $3$ 个连续的字符替换成这三个数的中位数。
求有多少将 $\texttt ?$ 替换成 $\texttt0$ 或 $\texttt1$ 的方案使得进行 $\frac{N-1}{2}$ 次操作后的字符串可以是 $\texttt1$。
输入格式:
一行,给定 $s$ 。
输出格式:
一行,答案
数据范围:
$1\leq N\leq300000$ 且 $N$ 为奇数。
做多替换三个的题了,还以为是把每个位置都换成中位数……(我就说大早上写题会弱智吧)
容易发现,如果一个字符串由 $a$ 个连续的 $\mathtt{1}$ 和 $b$ 个连续的 $\mathtt{0}$ 拼接而成,则当 $a > b$ 时一定合法。
考虑维护一个从栈顶到栈底由一段连续的 $\mathtt{0}$ 和一段连续的 $\mathtt{1}$ 组成的栈,然后依次加入每个 $s_i$ ,则
- 若 $s_i = \mathtt{0}$ ,
- 若栈顶为 $\mathtt 0$ ,当栈顶有 $2$ 个 $\mathtt 0$ 时可以替换成一个 $\mathtt 0$ ,否则入栈。
- 若栈顶为 $\mathtt 1$ ,直接入栈。
- 若 $s_i = \mathtt{1}$ ,
- 若栈顶为 $\mathtt 0$ ,新加入的 $\mathtt 1$ 可以和栈顶的 $\mathtt 0$ 抵消。
- 若栈顶为 $\mathtt 1$ ,仅在 $\mathtt 1$ 只有一个时加入。
那么这个栈就用很小的状态数就维护了一个串是否合法。
于是可以考虑 dp 了。设 $f(i,a,b)$ 为考虑到第 $i$ 位,栈内有 $a$ 个 $\mathtt 1$ 和 $b$ 个 $\mathtt 0$ 的方案数,考虑转移:
若 $s_{i+1}=\mathtt 0$ ,则
若 $s_{i+1} = \mathtt 1$ ,则
若 $s_{i + 1} = \mathtt{?}$ ,则把上面两种转移都做一遍即可。
时间复杂度 $\mathcal{O}(n)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
const int mod = 1e9 + 7;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
void add(int &x, int y) { (x += y) >= mod ? x -= mod : 0; }
#define N ((int)(3e5 + 15))
char s[N];
int n, f[N][3][3];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> (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++)
{
add(f[i + 1][a][1], f[i][a][2]);
add(f[i + 1][a][2], f[i][a][1]);
add(f[i + 1][a][1], f[i][a][0]);
}
}
if(s[i + 1] != '0') {
for(int a = 0; a <= 2; a++)
{
add(f[i + 1][a][0], f[i][a][1]);
add(f[i + 1][a][1], f[i][a][2]);
}
add(f[i + 1][1][0], f[i][0][0]);
add(f[i + 1][2][0], f[i][1][0]);
add(f[i + 1][2][0], f[i][2][0]);
}
}
int res = 0;
for(int a = 0; a <= 2; a++)
for(int b = 0; b <= a; b++) add(res, f[n][a][b]);
cout << res << '\n';
return 0;
}
参考文献:
[1] https://www.luogu.com.cn/article/t1y87bs5
题外话:
题又不会做…睡觉睡觉(困)