NC213856. [CSP2020]函数调用(call)
描述
题目数据为官方数据,可以提交测试,结果仅供参考,不代表官方成绩,最终成绩以官方发布的最终成绩为准。
在使用该数据库应用时,用户可一次性输入要调用的函数序列(一个函数可能被调用多次),在依次执行完序列中的函数后,系统中的数据被加以更新。某一天,小 A 在应用该数据库程序处理数据时遇到了困难:由于频繁而低效的函数调用,系统在执行操作时进入了无响应的状态,他只好强制结束了数据库程序。为了计算出正确数据,小 A 查阅了软件的文档,了解到每个函数的具体功能信息,现在他想请你根据这些信息帮他计算出更新后的数据应该是多少。
输入描述
第 行一个正整数 ,表示数据的个数。
第 行 个整数,第 个整数表示下标为 的数据的初始值为 。
第 行一个正整数 ,表示数据库应用程序提供的函数个数。函数从 编号。
接下来 行中,第 行的第一个整数为 ,表示 号函数
的类型:1.若 ,接下来两个整数 分别表示要执行加法的元素的下标及其增加的值;2.若 ,接下来一个整数 表示所有元素所乘的值;3.若 ,接下来一个正整数 表示 号函数要调用的函数个数,随后 个整数 依次表示其所调用的函数的编号。第 行一个正整数 ,表示输入的函数操作序列长度。
第 行 个整数 ,第 个整数表示第 个执行的函数的编号。
输出描述
一行 个用空格隔开的整数,按照下标 的顺序,分别输出在执行完输入的函数序列后,数据库中每一个元素的值。答案对 998244353 取模。
示例1
输入:
3 1 2 3 3 1 1 1 2 2 3 2 1 2 2 2 3
输出:
6 8 12
说明:
1 号函数功能为将 的值加一。2 号函数功能为所有元素乘 2。3 号函数将先调用 1 号函数,再调用 2 号函数。示例2
输入:
10 1 2 3 4 5 6 7 8 9 10 8 3 2 2 3 3 2 4 5 3 2 5 8 2 2 3 2 6 7 1 2 5 1 7 6 2 3 3 1 2 3
输出:
36 282 108 144 180 216 504 288 324 360
说明:
对于所有数据:,,,, ,。C++(g++ 7.5.0) 解法, 执行用时: 99ms, 内存消耗: 16368K, 提交时间: 2023-08-05 14:40:40
#include <bits/stdc++.h> using namespace std; #define ll long long inline ll read(){ ll x=0,sign=0; char s=getchar(); while(s>'9'||s<'0')sign|=s=='-',s=getchar(); while(s<='9'&&s>='0')x=(x<<1)+(x<<3)+s-'0',s=getchar(); return sign?-x:x; } const int N=1e5+5; const int mod=998244353; int n,m,c,a[N],deg[N],func[N]; int tp[N],pos[N],val[N]; ll mu=1,mul[N],dp[N],add[N]; vector <int> e[N]; queue <int> q; bool vis[N]; void dfs(int id){ vis[id]=1,mul[id]=(tp[id]==2?val[id]:1); for(int it:e[id]){ if(!vis[it])dfs(it); mul[id]=mul[id]*mul[it]%mod; } } int main(){ n=read(); for(int i=1;i<=n;i++)a[i]=read(); m=read(); for(int i=1;i<=m;i++){ tp[i]=read(); if(tp[i]==1)pos[i]=read(),val[i]=read(); else if(tp[i]==2)val[i]=read(); else{ c=read(); while(c--){ int to=read(); e[i].push_back(to),deg[to]++; } } } c=read(); for(int i=1;i<=m;i++)if(!vis[i]&&!deg[i])dfs(i); for(int i=1;i<=c;i++)func[i]=read(); for(int i=c,f=func[i];i;i--,f=func[i]){ if(tp[f]==1)dp[f]=(dp[f]+mu); else if(tp[f]==2)mu=mu*val[f]%mod; else dp[f]=(dp[f]+mu),mu=mu*mul[f]%mod; } for(int i=1;i<=m;i++)if(!deg[i])q.push(i); while(!q.empty()){ int t=q.front(); q.pop(); if(tp[t]==1)add[pos[t]]=(add[pos[t]]+dp[t]*val[t])%mod; ll z=dp[t]; reverse(e[t].begin(),e[t].end()); for(int p:e[t]){ deg[p]--; if(!deg[p])q.push(p); dp[p]=(dp[p]+z)%mod,z=z*mul[p]%mod; } } for(int i=1;i<=n;i++)cout<<(a[i]*mu+add[i])%mod<<" "; return 0; }
C++(clang++11) 解法, 执行用时: 208ms, 内存消耗: 13564K, 提交时间: 2020-11-08 18:25:00
#include<cstdio> #include<algorithm> #include<vector> #include<queue> using namespace std; const int N=1e5+5; const int mod=998244353; int n,m,a[N],b[N],x[N],y[N],ind[N],seq[N],len,mul[N],val[N]; vector<int>vec[N]; queue<int>Q; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&a[i]); scanf("%d",&m); for(int i=1,t,k,g;i<=m+1;++i){ if(i<=m) scanf("%d",&t); else t=3; mul[i]=1; if(t==1) scanf("%d%d",&x[i],&y[i]); if(t==2) scanf("%d",&mul[i]); if(t==3){ scanf("%d",&k); while(k--){ scanf("%d",&g); vec[i].push_back(g); ++ind[g]; } } } for(int i=1;i<=m+1;++i) if(!ind[i]) Q.push(i); while(!Q.empty()){ int u=Q.front(); Q.pop(); seq[++len]=u; for(int v:vec[u]) if(!--ind[v]) Q.push(v); } for(int i=m+1;i;--i) for(int j:vec[seq[i]]) mul[seq[i]]=1ll*mul[seq[i]]*mul[j]%mod; val[m+1]=1; for(int i=1;i<=m+1;++i){ int u=seq[i]; if(x[u]) b[x[u]]=(b[x[u]]+1ll*val[u]*y[u])%mod; reverse(vec[u].begin(),vec[u].end()); for(int v:vec[u]){ val[v]=(val[v]+val[u])%mod; val[u]=1ll*val[u]*mul[v]%mod; } } for(int i=1;i<=n;++i) printf("%lld%c",(1ll*a[i]*mul[m+1]+b[i])%mod,i==n?'\n':' '); return 0; }