记录编号 |
571709 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[CSP 2020S]函数调用 |
最终得分 |
100 |
用户昵称 |
yuan |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
1.343 s |
提交时间 |
2022-06-14 10:55:33 |
内存使用 |
65.85 MiB |
显示代码纯文本
#include<bits/stdc++.h>
#define LL long long
#define mod 998244353
#define N 1100005
using namespace std;
LL n,m,q;
LL a[N];//序列
LL addid[N],addval[N],num[N],mul[N];
struct edge
{
LL to,nxt;
}e[N];//调用关系,总数 <= sum(Cj)+Q
LL head[N],cnt=0;
LL ind[N];//入度
bool vis[N];
void add(LL u,LL v)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(LL from)
{//求解mul[i]:调用函数i对全局乘的倍数贡献;
vis[from]=1;//访问标记
for(LL i=head[from];i;i=e[i].nxt)
{
LL to=e[i].to;//被调函数
if(!vis[to]) dfs(to);
mul[from]=mul[from]*mul[to]%mod;
//被调函数处理完后,更新mul[from]
}
}
void toposort()
{//按拓扑序下传函数调用次数num[]
queue<LL>q;
for(LL i=0;i<=m;i++) if(!ind[i]) q.push(i);
num[0]=1;
while(!q.empty())
{
LL from=q.front(); q.pop();//取队头
LL cur_mul=1;//初始化当前倍数贡献
for(LL i=head[from];i;i=e[i].nxt)
{//倒序处理调用的子函数(链式前向星存储保证边倒序)
LL to=e[i].to;
//+=父结点调用次数 * 已处理兄弟结点mul[]之积
(num[to] += num[from] * cur_mul % mod) %= mod;
cur_mul = cur_mul * mul[to] % mod;//更新当前倍数贡献
ind[to]--;//入度减1
if(!ind[to]) q.push(to);
}
}
}
int main()
{
freopen("2020call.in","r",stdin);
freopen("2020call.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);//数列a
scanf("%lld",&m);//函数个数
for(int i=1;i<=m;i++)
{
LL op;//函数类型
scanf("%lld",&op);
if(op==1)//元素加
{
scanf("%lld%lld",&addid[i],&addval[i]);
mul[i]=1;
}
if(op==2)//全局乘
{
scanf("%lld",&mul[i]);
}
if(op==3)//调用函数序列
{
LL C;
scanf("%lld",&C);
mul[i]=1;
for(LL j=1;j<=C;j++)
{
LL g;
scanf("%lld",&g);
add(i,g);//函数i调用函数g
ind[g]++;//函数g入度+1
}
}
}
scanf("%lld",&q);
for(LL i=1;i<=q;i++)
{
LL f;
scanf("%lld",&f);
add(0,f);//从0到所有询问函数序列中的函数连边
ind[f]++;
}
mul[0]=1;
dfs(0);//求解mul[]
for(int i=1;i<=n;i++)
a[i] = a[i] * mul[0] % mod;//数列元素乘以全局倍数
toposort();//按拓扑序下传函数调用次数
for(int i=1;i<=m;i++)//处理单点修改
if(addval[i])//a[i]+=调用次数num[i] * 单次修改值addval[i]
(a[addid[i]]+=num[i]*addval[i]%mod)%=mod;
for(int i=1;i<=n;i++) printf("%lld ",a[i]);
return 0;
}