题目
Description
Input
Output
行,每行一个数表示第 次修改后的答案
Sample Input
样例输入1:
5 3
3
1 3 1
2 2 3 1
1 1 1
4
4 2 2
2 3 3
3 2 2 1
样例输入2:
9 7
3
1 2 2
2 1 2 2
1 2 1
4
2 2 2 1
3
1 2 1
4
4 2 2
2 2 1
4 1 1
4 2 1
8 1 2
4 2 1
2 2 2
Sample Output
样例输出1:
561512449
790276780
499122177
样例输出2:
236251164
632221424
632221424
360846848
29577611
29577611
366022930
Data Constraint
有 20 个测试点
思路
码 农 题
首先考虑没有括号的情况
因为求值顺序是从左向右,因此对于一段type为212121的串,它的运算结果可以写成一个2*2的矩阵,表示如果左边运算结果是0/1,算到右边是0/1的概率
显然可以用线段树来维护
然后考虑有括号的
这相当于给你一棵树的中序遍历表达式,所以我们可以把它还原成树。
考虑在这样的树上修改一个点,它只会改变它到树的根上每个点对应的括号是0/1的概率
如果暴力更改,时间复杂度就会出问题。
所以我们可以考虑链剖。
对于每个点,维护一个2*2的矩阵,表示它的重儿子是0/1时它的结果是0/1的概率
每次修改时先修改这个点,求出这个点新的概率,然后在它父亲的线段树上修改,然后跳到父亲的链顶,重复这个过程
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+77,mod=998244353;
struct AA
{
int tp;
ll x,y,z;
}A[N];
struct Sq
{
ll a[2][2];
void clear() {memset(a,0,sizeof(a));}
}tr[N*4],_1,c,S[N];
struct E
{
int to,next;
}e[N*2];
int ls[N],bg[N],size[N],d[N],fa[N],nx[N],nx2[N],top[N],end[N],n,Q,i,j,k,l,cnt,root,tot,h,t;
ll x,y,z;
ll power(ll a,int b)
{
ll yjy=1;
while(b)
{
if(b&1) yjy=yjy*a%mod;
a=a*a%mod; b>>=1;
}
return yjy;
}
void add(int x,int y) {++cnt;e[cnt].to=y;e[cnt].next=ls[x];ls[x]=cnt;}
Sq mul(Sq a,Sq b)
{
Sq c;
int i,j,k;
for(i=0; i<=1; i++)
{
for(j=0; j<=1; j++)
{
c.a[i][j]=0;
for(k=0; k<=1; k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
}
}
return c;
}
void work()
{
int d[N],i,j,k,l,t=0;
for(i=1; i<=n; i++)
{
switch (A[i].tp)
{
case 1:{d[++t]=i;break;}
case 2:{d[++t]=i;break;}
case 3:{d[++t]=-1;break;}
case 4:{
if(d[t-1]==-1)
{
d[t-1]=d[t]; --t; break;
}
j=t;while(d[j-1]!=-1) j-=2;
add(d[j+1],d[j]); for(k=j; k<t; k+=2) {add(d[k+1],d[k+2]); if(k+3<=t) add(d[k+3],d[k+1]);};
d[j-1]=d[t-1],t=j-1;
break;
}
}
}
if(t>1)
{
add(d[2],d[1]);
for(k=1; k<t; k+=2)
{
add(d[k+1],d[k+2]);
if(k+3<=t) add(d[k+3],d[k+1]);
}
root=d[t-1];
}
else root=d[1];
}
void dfs()
{
int i,mx=0;
h=0;t=1;
d[1]=root;
while(h<t)
{
for(i=ls[d[++h]]; i; i=e[i].next)
fa[e[i].to]=d[h],d[++t]=e[i].to;
}
while(t)
{
size[d[t]]=1;mx=0;
for(i=ls[d[t]]; i; i=e[i].next)
{
size[d[t]]+=size[e[i].to];
if(size[e[i].to]>mx)
mx=size[e[i].to],nx[d[t]]=e[i].to;
}
--t;
}
}
void dfs2()
{
int i,j,k;
h=0;t=1;
d[1]=root;
while(h<t)
{
i=j=d[++h];
while(nx[j]) j=nx[j];
do{
for(k=ls[i]; k; k=e[k].next)
if(e[k].to!=nx[i])
nx2[i]=e[k].to,d[++t]=e[k].to;
bg[i]=++tot;
top[i]=d[h];
end[i]=j;
i=nx[i];
}
while(i);
}
}
void ins(int t,int l,int r,int x,Sq s)
{
int mid=(l+r)/2;
if(l==r) {tr[t]=s;return;}
if(x<=mid) ins(t*2,l,mid,x,s);
else ins(t*2+1,mid+1,r,x,s);
tr[t]=mul(tr[t*2+1],tr[t*2]);
}
Sq search(int t,int l,int r,int x,int y)
{
int mid=(l+r)/2;
Sq yjy=_1,s;
if(x<=l && r<=y) {return tr[t];}
if(mid<y) s=search(t*2+1,mid+1,r,x,y),yjy=mul(yjy,s);
if(x<=mid) s=search(t*2,l,mid,x,y),yjy=mul(yjy,s);
return yjy;
}
Sq js(int t,Sq B)
{
ll a=B.a[0][0],b=B.a[0][1];
Sq c;
c.a[0][0]=(A[t].x+A[t].y*a+A[t].z*a)%mod;
c.a[0][1]=(A[t].y*b+A[t].z*b)%mod;
c.a[1][0]=(A[t].x*a+A[t].z*b)%mod;
c.a[1][1]=(A[t].x*b+A[t].y+A[t].z*a)%mod;
return c;
}
Sq get(int t)
{
return search(1,1,tot,bg[t],bg[end[t]]);
}
void Dfs()
{
Sq c;
h=0;t=1;
d[1]=root;
while(h<t)
{
for(i=ls[d[++h]]; i; i=e[i].next)
d[++t]=e[i].to;
}
while(t)
{
if(nx[d[t]])
{
c=js(d[t],S[nx2[d[t]]]);
S[d[t]]=mul(S[nx[d[t]]],c);
ins(1,1,tot,bg[d[t]],c);
}
else
{
S[d[t]].a[1][0]=S[d[t]].a[1][1]=0;S[d[t]].a[0][0]=A[d[t]].x;S[d[t]].a[0][1]=A[d[t]].y;
ins(1,1,tot,bg[d[t]],S[d[t]]);
}
--t;
}
}
void solve(int t)
{
while(t)
{
t=top[t];
if(!fa[t]) break;
ins(1,1,tot,bg[fa[t]],js(fa[t],get(t)));
t=fa[t];
}
}
int main()
{
freopen("structure.in","r",stdin); freopen("structure.out","w",stdout);
_1.a[0][0]=_1.a[1][1]=1;
scanf("%d%d",&n,&Q);
for(i=1; i<=n; i++)
{
scanf("%d",&A[i].tp);
if(A[i].tp==1) scanf("%lld%lld",&A[i].x,&A[i].y),l=power((A[i].x+A[i].y)%mod,(mod-2));
if(A[i].tp==2) scanf("%lld%lld%lld",&A[i].x,&A[i].y,&A[i].z),l=power((A[i].x+A[i].y+A[i].z)%mod,(mod-2));
if(A[i].tp<=2) A[i].x=A[i].x*l%mod,A[i].y=A[i].y*l%mod,A[i].z=A[i].z*l%mod;
}
work();
dfs();
tot=0;top[root]=root;
dfs2();
Dfs();
while(Q--)
{
scanf("%d%lld%lld",&t,&x,&y);
if(A[t].tp==2) scanf("%lld",&z); else z=0;
l=power(x+y+z,(mod-2));
x=x*l%mod,y=y*l%mod,z=z*l%mod;
switch(A[t].tp)
{
case 1:
{
c.a[1][0]=c.a[1][1]=0;c.a[0][0]=x;c.a[0][1]=y;
ins(1,1,tot,bg[t],c);
break;
}
case 2:
{
A[t].x=x;A[t].y=y;A[t].z=z;
ins(1,1,tot,bg[t],js(t,get(nx2[t])));
break;
}
}
solve(t);
c=get(root);
printf("%lld\n",c.a[0][1]);
}
}