( ext{Solution})
其实并不是一道难题,只是不知道如何一步步算。
首先想算出每个 (1) 操作的系数,这样能省去很多重复步骤。
观察到 (1) 操作可以被分成单个函数(指直接出现在函数操作序列中)和被引用函数(被直接出现在函数操作序列中的第 (3) 类函数引用)。
对于每个(一种函数可能在函数操作序列中被直接调用多次)单个函数我们需要算出在调用它之后调用的 (2) 操作之积,显然这就是对于这个单个函数的系数。我们将这种函数的每个单个函数的系数相加,显然就是这种函数的单个函数的总系数。
那被引用函数呢?我们只要向上面那样,算出第 (3) 类函数的系数,再下传给它就好了(注意这是一个 ( ext{DAG}),所以用拓扑排序来下传)。
详见注释。
( ext{Code})
#include <cstdio>
#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)
int read() {
int x=0,f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
void write(int x) {
if(x<0) return (void)(putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
#include <queue>
#include <vector>
using namespace std;
const int maxn=1e5+5,mod=998244353;
int n,m,Q,a[maxn],op[maxn],pos[maxn],val[maxn],id[maxn],deg[maxn],mul[maxn],Add[maxn],f[maxn];
vector <int> g[maxn];
queue <int> q;
bool vis[maxn];
void dfs(int u) {
if(vis[u]) return;
vis[u]=1;
mul[u]=(op[u]==2?val[u]:1); // mul: 直接引用第 3 类函数会导致翻多少倍
for(int i=0;i<g[u].size();++i) {
int v=g[u][i];
dfs(v);
mul[u]=1ll*mul[u]*mul[v]%mod;
}
}
void topol() {
int Mul;
rep(i,1,m) if(!deg[i]) q.push(i);
while(!q.empty()) {
int u=q.front(); q.pop();
if(op[u]==1) Add[pos[u]]=(Add[pos[u]]+1ll*f[u]*val[u]%mod)%mod; // 注意不能在后面插入队列时更新,不然本来就无子的就无法更新
Mul=f[u];
for(int i=g[u].size()-1;i>=0;--i) {
int v=g[u][i];
--deg[v];
if(!deg[v]) q.push(v);
f[v]=(f[v]+Mul)%mod; Mul=1ll*Mul*mul[v]%mod; // 这里是为了算间接引用时 v 的贡献:父亲们的系数 * 在自己后面的兄弟的系数
}
}
}
int main() {
int x,y;
n=read();
rep(i,1,n) a[i]=read();
m=read();
rep(i,1,m) {
op[i]=read();
if(op[i]==1) pos[i]=read(),val[i]=read();
else if(op[i]==2) val[i]=read();
else {
x=read();
rep(j,1,x) y=read(),++deg[y],g[i].push_back(y);
}
}
Q=read();
rep(i,1,Q) id[i]=read();
rep(i,1,m) if(!deg[i]) dfs(i);
y=1;
for(int i=Q;i>=1;--i) {
x=id[i];
if(op[x]==1) f[x]=(f[x]+y)%mod;
else if(op[x]==2) y=1ll*y*mul[x]%mod;
else f[x]=(f[x]+y)%mod,y=1ll*y*mul[x]%mod; // f 就是算函数在函数调用序列里翻了多少倍
}
topol();
rep(i,1,n) print((1ll*a[i]*y%mod+Add[i])%mod,' '); puts("");
return 0;
}