事先聲明,考試時由於本人太菜,T1寫了兩個小時還tm沒判12.31掛了所以只是口胡了個拓撲排序,直接打了40分,考完自閉了很久之后才碼出來
首先我們發現由於不會遞歸,所以把所有操作連起來會形成一張DAG,DAG上並沒有什么很好的數據結構可以維護,所以可以考慮分別考慮乘法和加法的影響,可以發現,最終值是初始值乘以一堆值再加上一堆值
又因為乘法顯然會對加法產生影響所以可以考慮,每個加法到最后都會加幾次
可以發現每個加法最后加幾次,等價於在這個加法之后,全局乘的數值的積,於是我們可以考慮倒着處理這個函數數列
每次加法的時候就加上標記,(前面乘的積),乘法就更新全局積,如果是遞歸,就先給它下轄(即最終會被調用的乘法或者加法)的所有加法加上標記(打在它本身上面,最終拓撲排序下傳),然后再用下面的乘法更新全局積
最后打完標記最后拓撲排序下傳一下就行.具體地依然從后往前處理,注意要更新一下最終加法的次數(類似於線段樹合並,處理右兒子時要考慮左兒子的貢獻),具體看代碼吧
其實也不是很難,還是我太菜了
/*call*/ #include<bits/stdc++.h> using namespace std; int read(){ char c = getchar(); int x = 0; while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') x = x * 10 + c - 48,c = getchar(); return x; } const int maxn = 1e6 + 10; struct Edge{ int nxt,point; }edge[maxn<<1]; int a[maxn]; int head[maxn],tot; int deg[maxn]; void add_edge(int x,int y){ edge[++tot].nxt = head[x]; edge[tot].point = y; head[x] = tot; deg[y]++; } struct Func{ int op; int p,v; }f[maxn]; int seq[maxn]; int C = 1; int tag[maxn]; #define mod 998244353 int mul[maxn]; void add(int &x,int y){ x += y - mod; x += (x >> 31) & mod; } void sol(int x){ if(f[x].op == 1){ add(tag[f[x].p],1ll * C * f[x].v % mod) ; return; } else if(f[x].op == 2){ C = 1ll * C * f[x].v % mod; } else{ for(int i = head[x]; i; i = edge[i].nxt){ sol(edge[i].point); } } } void dfs(int x){ if(~mul[x]) return; mul[x] = 1; if(f[x].op == 1) return; if(f[x].op == 2){ mul[x] = f[x].v; return; } for(int i = head[x]; i ; i = edge[i].nxt) dfs(edge[i].point),mul[x] = 1ll * mul[x] * mul[edge[i].point] % mod; } int q[maxn]; int main(){ int n = read(); for(int i = 1; i <= n; ++i) a[i] = read(); int m = read(); for(int i = 1; i <= m; ++i){ int op = read(); f[i].op = op; if(op == 1){ f[i].p = read(),f[i].v = read(); } else if(op == 2){ f[i].v = read(); } else{ int s = read(); for(int j = 1; j <= s; ++j){ int x = read(); add_edge(i,x); } } } memset(mul,-1,sizeof(mul)); int t = read(); for(int i = 1; i <= t; ++i) seq[i] = read(); for(int i = 1; i <= m; ++i) dfs(i); for(int x = t; x; --x){ if(f[seq[x]].op == 1) add(tag[seq[x]],C); if(f[seq[x]].op == 2) C = 1ll * C * f[seq[x]].v % mod; if(f[seq[x]].op == 3){ add(tag[seq[x]],C); C = 1ll * C * mul[seq[x]] % mod; } } for(int i = 1; i <= n; ++i) a[i] = 1ll * a[i] * C % mod; int l = 1,r = 0; for(int i = 1; i <= m; ++i) if(!deg[i]) q[++r] = i; while(l <= r){ int x = q[l++]; if(f[x].op == 1){ add(a[f[x].p],1ll * tag[x] * f[x].v % mod); continue; } if(f[x].op == 2) continue; int v = 1; for(int i = head[x]; i ; i = edge[i].nxt){ int y = edge[i].point; add(tag[y],1ll * tag[x] * v % mod); --deg[y];if(!deg[y]) q[++r] = y; v = 1ll * v * mul[y] % mod; } } for(int i = 1; i <= n; ++i) printf("%d%c",a[i]," \n"[i == n]); return 0; }