[ABC246Ex] 01? Queries

[ABC246Ex] 01? Queries

基础动态 dp 练习题。

题意

初始时给定一个长度为 \(n\),值域为 \(\{0,1,?\}\) 的字符串。

接下来有 \(q\) 次操作。每次操作给定 \(x_i\)\(c_i\),把第 \(x_i\) 个字符改为 \(c_i\)

每次操作后,你需要将每个 \(?\) 替换为 \(0\)\(1\),求可能构成的本质不同非空子序列个数 \(\bmod \space 998244353\)

比如对于 \(101\),其本质不同非空子序列有 \(0\)\(1\)\(10\)\(01\)\(101\)\(5\) 个。

\(1 \leq n,q \leq 10^5\)\(1 \leq x_i \leq n\)\(c_i \in \{0,1,?\}\)

思路

先考虑静态问题。以下用 \(s_i\) 代指字符串的第 \(i\) 个字符。

我们令 \(dp_{i,c}\)\(i\) 个字符可以形成的以 \(c\) 结尾的本质不同非空子序列个数。

\(s_i=0\) 时,\(dp_{i,0}=dp_{i-1,0}+dp_{i-1,1}+1\)\(dp_{i,1}=dp_{i-1,1}\)

\(s_i=1\) 时,\(dp_{i,0}=dp_{i-1,0}\)\(dp_{i,1}=dp_{i-1,0}+dp_{i-1,1}+1\)

\(s_i=?\) 时,\(dp_{i,0}=dp_{i-1,0}+dp_{i-1,1}+1\)\(dp_{i,1}=dp_{i-1,0}+dp_{i-1,1}+1\)

所以当 \(s_i=0\) 时:

\[\begin{bmatrix} 1 & 1 & 1\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} dp_{i-1,0}\\ dp_{i-1,1}\\ 1 \end{bmatrix} = \begin{bmatrix} dp_{i,0}\\ dp_{i,1}\\ 1 \end{bmatrix} \]

\(s_i=1\) 时:

\[\begin{bmatrix} 1 & 0 & 0\\ 1 & 1 & 1\\ 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} dp_{i-1,0}\\ dp_{i-1,1}\\ 1 \end{bmatrix} = \begin{bmatrix} dp_{i,0}\\ dp_{i,1}\\ 1 \end{bmatrix} \]

\(s_i=?\) 时:

\[\begin{bmatrix} 1 & 1 & 1\\ 1 & 1 & 1\\ 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} dp_{i-1,0}\\ dp_{i-1,1}\\ 1 \end{bmatrix} = \begin{bmatrix} dp_{i,0}\\ dp_{i,1}\\ 1 \end{bmatrix} \]

并且我们有:

\[\begin{bmatrix} dp_{0,0}\\ dp_{0,1}\\ 1 \end{bmatrix} = \begin{bmatrix} 0\\ 0\\ 1 \end{bmatrix} \]

所以我们使用线段树维护每个点的转移矩阵就可以了。时间复杂度 \(O(n+q \log n)\)

代码

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const long long mod=998244353;
struct Matrix{
	long long matrix[3][3];
}I=(Matrix){{{1,0,0},{0,1,0},{0,0,1}}},zero=(Matrix){{{1,1,1},{0,1,0},{0,0,1}}},one=(Matrix){{{1,0,0},{1,1,1},{0,0,1}}},mark=(Matrix){{{1,1,1},{1,1,1},{0,0,1}}};
const Matrix operator *(const Matrix &x,const Matrix &y){
	Matrix z;
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			z.matrix[i][j]=0;
			for(int k=0;k<3;k++){
				z.matrix[i][j]+=x.matrix[i][k]*y.matrix[k][j]%mod;
				z.matrix[i][j]%=mod;
			}
		}
	}
	return z;
}
char s[100010];
Matrix trans(char ch){
	if(ch=='0') return zero;
	else if(ch=='1') return one;
	else return mark;
}
struct Node{
	int l,r;
	Matrix g;
}a[400010];
void pushup(int id){
	a[id].g=a[id*2].g*a[id*2+1].g;
}
void build(int id,int l,int r){
	a[id].l=l;
	a[id].r=r;
	if(a[id].l==a[id].r){
		a[id].g=trans(s[l]);
	}
	else{
		int mid=(l+r)>>1;
		build(id*2,l,mid);
		build(id*2+1,mid+1,r);
		pushup(id);
	}
}
void modify(int id,int pos){
	if(a[id].l==a[id].r){
		a[id].g=trans(s[pos]);
		return ;
	}
	if(pos<=a[id*2].r){
		modify(id*2,pos);
	}
	else{
		modify(id*2+1,pos);
	}
	pushup(id);
}
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		cin>>s[i];
	}
	build(1,1,n);
	while(m--){
		int p;
		char c;
		scanf("%d",&p);
		cin>>c;
		s[p]=c;
		modify(1,p);
		printf("%lld\n",(a[1].g.matrix[0][2]+a[1].g.matrix[1][2])%mod);
	}
	return 0;
}
posted @ 2025-05-18 23:21  Oken喵~  阅读(2)  评论(0)    收藏  举报