题目

Description
【JZOJ 省选模拟】Easy Data Structure_题组

Input
【JZOJ 省选模拟】Easy Data Structure_题组_02

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 个测试点
【JZOJ 省选模拟】Easy Data Structure_题组_03

思路

码 农 题

首先考虑没有括号的情况
因为求值顺序是从左向右,因此对于一段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]);
	}
}