[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\) 时:
当 \(s_i=1\) 时:
当 \(s_i=?\) 时:
并且我们有:
所以我们使用线段树维护每个点的转移矩阵就可以了。时间复杂度 \(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;
}

浙公网安备 33010602011771号