1. 程式人生 > 其它 >P7077 [CSP-S2020] 函式呼叫

P7077 [CSP-S2020] 函式呼叫

預處理出函式 \(i\) 乘上的係數 \(mul_i\),顯然函式之間的呼叫關係形成了一張拓撲圖。

不妨將整個程式視為一個型別 \(3\) 的函式,從其開始拓撲排序。記 \(k_i\) 表示位置 \(i\) 當前加上的數,\(f_i\) 表示函式 \(i\) 當前對其中加法函式的呼叫次數

注意到一個加法函式產生的貢獻只取決於加數呼叫次數,後者我們可以通過累加的方式來得到;一個

  • 型別 \(1\)。此後再也不會呼叫它了,那麼它的貢獻可以算好了:\(k_{P_i}\gets k_{P_i}+V_i\times f_i\)
  • 型別 \(2\)。其貢獻在 \(mul\) 中,直接忽略。
  • 型別 \(3\)
    。因為前面的乘法能影響到後面的加法,所以考慮倒序遍歷。
    函式 \(i\) 呼叫了函式 \(j\)\(f_j\gets f_j+f_i,f_i\gets f_i\times mul_j\)

注意沒出現過的函式要刪掉出邊以免影響拓撲排序。時間複雜度 \(O(n)\)

code:

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define NN 1000005
#define Mod 998244353
#define For(i,x,y)for(i=x;i<=(y);i++)
struct node
{
	int next,to;
}e[2000005];
bool vis[NN];
queue<int>que;
int head[NN],p[NN],val[NN],t[NN],mul[NN],deg[NN],f[NN],a[N],k[N],g;
int read()
{
	int A;
	bool K;
	char C;
	C=A=K=0;
	while(C<'0'||C>'9')K|=C=='-',C=getchar();
	while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
	return(K?-A:A);
}
inline void add(int u,int v)
{
	e[++g].to=v;
	e[g].next=head[u];
	head[u]=g;
}
void dfs(int u)
{
	if(vis[u])return;
	int v,i;
	vis[u]=1;
	if(t[u]==2)mul[u]=val[u];
	else if(t[u]==3)
	{
		mul[u]=1;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].to;
			dfs(v);
			mul[u]=1LL*mul[u]*mul[v]%Mod;
		}
	}
	else mul[u]=1;
}
int main()
{
//	freopen("call.in","r",stdin);
//	freopen("call.out","w",stdout);
	int n,i,m,c,x,u,v,q;
	n=read();
	For(i,1,n)a[i]=read();
	m=read();
	For(i,1,m)
	{
		t[i]=read();
		if(t[i]==1)p[i]=read(),val[i]=read();
		else if(t[i]==2)val[i]=read();
		else
		{
			c=read();
			while(c--)
			{
				x=read();
				add(i,x);
				deg[x]++;
			}
		}
	}
	t[++m]=3;
	q=read();
	while(q--)
	{
		x=read();
		add(m,x);
		deg[x]++;
	}
	mul[m]=f[m]=1;
	dfs(m);
	For(u,1,m)
	if(!vis[u])
	for(i=head[u];i;i=e[i].next)deg[e[i].to]--;
	que.push(m);
	while(!que.empty())
	{
		u=que.front();
		que.pop();
		if(t[u]==1)k[p[u]]=(k[p[u]]+1LL*val[u]*f[u])%Mod;
		else if(t[u]==3)
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].to;
			deg[v]--;
			if(!deg[v])que.push(v);
			/*printf("%d %d\n",u,v);*/
			f[v]=(f[v]+f[u])%Mod;
			f[u]=1LL*f[u]*mul[v]%Mod;
		}
	}
	For(i,1,n)printf("%d ",(1LL*a[i]*mul[m]+k[i])%Mod);
	return 0;
}