Problem Statement

You are given a string $S$ of length $N$ consisting of 0, 1, and ?.

You are also given $Q$ queries $(x_1, c_1), (x_2, c_2), \ldots, (x_Q, c_Q)$.

For each $i = 1, 2, \ldots, Q$, $x_i$ is an integer satisfying $1 \leq x_i \leq N$ and $c_i$ is one of the characters 0 , 1, and ?.

For $i = 1, 2, \ldots, Q$ in this order, do the following process for the query $(x_i, c_i)$.

  1. First, change the $x_i$-th character from the beginning of $S$ to $c_i$.
  2. Then, print the number of non-empty strings, modulo $998244353$, that can be obtained as a (not necessarily contiguous) subsequence of $S$ after replacing each occurrence of ? in $S$ with 0 or 1 independently.

Constraints

  • $1 \leq N, Q \leq 10^5$
  • $N$ and $Q$ are integers.
  • $S$ is a string of length $N$ consisting of 0, 1, and ?.
  • $1 \leq x_i \leq N$
  • $c_i$ is one of the characters 0 , 1, and ?.

Input

Input is given from Standard Input in the following format:

$N$ $Q$
$S$
$x_1$ $c_1$
$x_2$ $c_2$
$\vdots$
$x_Q$ $c_Q$

Output

Print $Q$ lines. For each $i = 1, 2, \ldots, Q$, the $i$-th line should contain the answer to the $i$-th query $(x_i, c_i)$ (that is, the number of strings modulo $998244353$ at the step 2. in the statement).


Sample Input 1

3 3
100
2 1
2 ?
3 ?

Sample Output 1

5
7
10
  • The $1$-st query starts by changing $S$ to 110. Five strings can be obtained as a subsequence of $S = $ 110: 0, 1, 10, 11, 110. Thus, the $1$-st query should be answered by $5$.

  • The $2$-nd query starts by changing $S$ to 1?0. Two strings can be obtained by the ? in $S = $ 1?0: 100 and 110. Seven strings can be obtained as a subsequence of one of these strings: 0, 1, 00, 10, 11, 100, 110. Thus, the $2$-nd query should be answered by $7$.

  • The $3$-rd query starts by changing $S$ to 1??. Four strings can be obtained by the ?'s in $S = $ 1??: 100, 101, 110, 111. Ten strings can be obtained as a subsequence of one of these strings: 0, 1, 00, 01, 10, 11, 100, 101, 110, 111. Thus, the $3$-rd query should be answered by $10$.


Sample Input 2

40 10
011?0??001??10?0??0?0?1?11?1?00?11??0?01
5 0
2 ?
30 ?
7 1
11 1
3 1
25 1
40 0
12 1
18 1

Sample Output 2

746884092
532460539
299568633
541985786
217532539
217532539
217532539
573323772
483176957
236273405

Be sure to print the count modulo $998244353$.

如果这个问题不是动态的,那要怎么做?想到dp做法。

定义 \(dp_{i,0/1}\) 为在前 \(i\) 个字符的所有子序列中,如果再加上 \(0/1\) 这个字符后,就不是前 \(i\) 个字符的子序列了的子序列个数。

那么如果遇到一个 \(1\),那么就相当于给所有加上 \(1\) 不属于前 \(i\) 个数的子序列加上了一个 \(1\),\(dp_{i,1}=dp_{i-1,1}\),然后新生成的这些子序列肯定再加上 \(0\) 后不属于前面的子序列,\(dp_{i,0}=dp_{i-1,1}+dp_{i-1,0}\).

如果遇到一个 \(0\) ,同理。遇到一个问好,\(dp_{i,1}=dp_{i,0}=dp_{i-1,1}+dp_{i-1,0}\)。

另开一个变量统计答案就可以了。

然后就要开始动态 dp,设 \((dp_0,dp_1,ans)\)为一个向量

遇到一个\(1\),向量乘上 \(\begin{Bmatrix}1&0&0\\1&1&1\\0&0&1 \end{Bmatrix}\)

遇到一个\(0\),向量乘上 \(\begin{Bmatrix}1&1&1\\0&1&0\\0&0&1 \end{Bmatrix}\)

遇到一个\(?\),向量乘上 \(\begin{Bmatrix}1&1&1\\1&1&1\\0&0&1 \end{Bmatrix}\)

剩下的就是用线段树维护矩阵乘法,单点修改,区间查询就可以了。

#include<bits/stdc++.h>
const int N=1e5+5,P=998244353;
int n,q,x;
char c;
struct matrix{
int a[4][4];
}t[3],tr[N<<2],p,dw;
matrix cheng(matrix a,matrix b)
{
matrix c;
memset(c.a,0,sizeof(c.a));
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
c.a[i][j]+=1LL*a.a[i][k]*b.a[k][j]%P,c.a[i][j]%=P;
return c;
}
int turn(char c)
{
if(c<='1')
return c-'0';
return 2;
}
void copy(matrix&a,matrix b)
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
a.a[i][j]=b.a[i][j];
}
void build(int o,int l,int r)
{
// printf("%d %d %d\n",o,l,r);
if(l>r)
return;
if(l==r)
{
scanf(" %c",&c);
copy(tr[o],t[turn(c)]);
return;
}
int md=l+r>>1;
build(o<<1,l,md);
build(o<<1|1,md+1,r);
copy(tr[o],cheng(tr[o<<1],tr[o<<1|1]));
}
void update(int o,int l,int r,int x,int y)
{
if(l==r)
{
copy(tr[o],t[y]);
return;
}
int md=l+r>>1;
if(md>=x)
update(o<<1,l,md,x,y);
else
update(o<<1|1,md+1,r,x,y);
copy(tr[o],cheng(tr[o<<1],tr[o<<1|1]));
}
int main()
{
scanf("%d%d",&n,&q);
p.a[1][1]=p.a[1][2]=1;
dw.a[1][1]=dw.a[2][2]=dw.a[3][3]=1;
for(int i=0;i<(N<<2);i++)
copy(tr[i],dw);
t[0].a[1][1]=t[0].a[2][1]=t[0].a[2][2]=t[0].a[2][3]=t[0].a[3][3]=1;
t[1].a[1][1]=t[1].a[1][2]=t[1].a[1][3]=t[1].a[2][2]=t[1].a[3][3]=1;
t[2].a[1][1]=t[2].a[1][2]=t[2].a[1][3]=t[2].a[2][1]=t[2].a[2][2]=t[2].a[2][3]=t[2].a[3][3]=1;
build(1,1,n);
while(q--)
{
scanf("%d %c",&x,&c);
update(1,1,n,x,turn(c));
printf("%d\n",cheng(p,tr[1]).a[1][3]);
}
}

[ABC246Ex] 01? Queries的更多相关文章

  1. Codeforces Round #371 (Div. 2) C. Sonya and Queries[Map|二进制]

    C. Sonya and Queries time limit per test 1 second memory limit per test 256 megabytes input standard ...

  2. Profiling MySQL queries from Performance Schema

    转自:http://www.percona.com/blog/2015/04/16/profiling-mysql-queries-from-performance-schema/ When opti ...

  3. 数据结构(线段树):CodeForces 145E Lucky Queries

    E. Lucky Queries time limit per test 3 seconds memory limit per test 256 megabytes input standard in ...

  4. Save results to different files when executing multi SQL statements in DB Query Analyzer 7.01

        1 About DB Query Analyzer DB Query Analyzer is presented by Master Genfeng,Ma from Chinese Mainl ...

  5. The new powerful SQL executing schedule monthly or weekly in DB Query Analyzer 7.01

    1 About DB Query Analyzer DB Query Analyzer is presented by Master Genfeng,Ma from Chinese Mainland. ...

  6. DB Query Analyzer 6.01 is released, SQL Execute Schedule function can be used

       DB Query Analyzer is presented by Master Gen feng, Ma from Chinese Mainland. It has English versi ...

  7. HDU6191(01字典树启发式合并)

    Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Othe ...

  8. 01: docker 基本使用

    1.1 docker基础 1.docker与虚拟机比较 2.docker版本 1. 社区版(Community Edition, CE) 2. 企业版(Enterprise Edition, EE) ...

  9. Codeforces Round #371 (Div. 2) C. Sonya and Queries 水题

    C. Sonya and Queries 题目连接: http://codeforces.com/contest/714/problem/C Description Today Sonya learn ...

  10. CSS3 响应式web设计,CSS3 Media Queries

    两种方式,一种是直接在link中判断设备的尺寸,然后引用不同的css文件: <link rel="stylesheet" type="text/css" ...

随机推荐

  1. 要调用API接口获取商品数据,首先需要了解该API的文档和规范

    ​ 要调用API接口获取商品数据,首先需要了解该API的文档和规范.大多数API都需要使用API密钥进行身份验证,因此您需要先注册API提供商,并从他们那里获取API密钥.以下是一些通用的步骤: 1. ...

  2. 按关键字API接口搜索天眼查企业数据

    一.如果你想要查找某一个企业的基本信息或是对行业中的企业进行筛选,那么使用API接口搜索天眼查企业数据会非常方便. 首先,你需要获取天眼查API的access_token,这可以通过注册账号获取.一旦 ...

  3. 解决Eclipse中启动Tomcat报unable to start within 45 seconds问题

    启动项目的时候报Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server ...

  4. 如何理解DDD中的值对象

    引言 实体和值对象是领域驱动设计中的两个重要概念.相对实体而言,值对象更加抽象,理解起来也更晦涩一些.那么该如何理解值对象?我们先来看一下<实现领域驱动设计>书中对值对象的定义: 值对象 ...

  5. ES 2023新特性速解

    ES 2023新特性速解 一.新增数组方法 操作数组的方法 Array.prototype.toSorted(compareFn) //返回一个新数组,其中元素按升序排序,而不改变原始数组. Arra ...

  6. 「hdu - 5780」gcd

    link. 钦定 \(i>j\),研究得 \((x^i-1,x^j-1)\rightleftharpoons(x^i-x^j,x^j-1)\rightleftharpoons(x^j(x^{i- ...

  7. 用Rust手把手编写一个Proxy(代理), UDP绑定篇

    用Rust手把手编写一个Proxy(代理), UDP绑定篇 项目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy github: https:// ...

  8. PostgreSQL学习笔记-2.基础知识:INSERT、SELECT、运算符、表达式、约束

    PostgreSQL INSERT INTO 语句用于向表中插入新记录,兼容SQL通用语法. 语法 INSERT INTO 语句语法格式如下: INSERT INTO TABLE_NAME (colu ...

  9. C#学习笔记---异常捕获和变量

    异常捕获 使用异常捕获可以捕获出现异常的代码块,防止因为异常抛出造成的程序卡死的情况发生. try{}catch{}finally{}结构 //异常捕获 try { string str=Consol ...

  10. 如何编写难以维护的 React 代码?耦合通用组件与业务逻辑

    在众多项目中,React代码的维护经常变得棘手.其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去"通用性".这种做法使通用组件过于依赖具体 ...