[CSP-S2020] 函数调用

前言

陈年旧账。

题目

洛谷

讲解

我们需要将这三种函数之间的互相影响的关系找出来。

可以发现操作一是最基础的,所以我们可以以此来计算贡献。

考虑操作二对操作一的影响,发现影响范围前面所有的操作一,显然我们需要逆序做。假如是乘 \(mul\),那么相当于操作一执行 \(mul\) 次,这个思想比较关键。

考虑操作三调用了很多复杂函数,但由于我们只考虑对操作一的影响,所以还是从后往前记录操作二的乘积,往前有操作一的时候乘上这个记录的值即可,相当于逆序求出操作一执行次数。

具体实现可以将 \(0\) 号点向操作序列连边,提前处理一下每个函数会将整体乘上多少,然后在 DAG 上拓扑排序即可。

代码

说实话,挺短
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;

typedef long long LL;
const int MAXN = 100005;
const int MOD = 998244353; 
int n,m;
int a[MAXN],mul[MAXN],add[MAXN],pos[MAXN],cnt[MAXN],deg[MAXN]; 

LL Read()
{
	LL x = 0,f = 1; char c = getchar();
	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

vector<int> G[MAXN];

bool vis[MAXN];
void dfs(int x)
{
	vis[x] = 1;
	for(auto v : G[x]) 
	{
		if(!vis[v]) dfs(v);
		mul[x] = 1ll * mul[x] * mul[v] % MOD;
	}
}
void topu()
{
	queue<int> q;
	for(int i = 0;i <= m;++ i) if(!deg[i]) q.push(i);
	while(!q.empty())
	{
		int x = q.front(),now = 1; q.pop();
		reverse(G[x].begin(),G[x].end());
		for(auto v : G[x])
		{
			cnt[v] = (cnt[v] + 1ll * cnt[x] * now) % MOD;
			now = 1ll * now * mul[v] % MOD;
			if(!(--deg[v])) q.push(v);
		}
	}
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read();
	for(int i = 1;i <= n;++ i) a[i] = Read();
	m = Read();
	for(int i = 1;i <= m;++ i)
	{
		int opt = Read(); mul[i] = 1;
		if(opt == 1) pos[i] = Read(),add[i] = Read();
		else if(opt == 2) mul[i] = Read();
		else 
		{
			int k = Read();
			for(int j = 0,v;j < k;++ j)
			{
				v = Read();
				G[i].emplace_back(v);
				++deg[v];
			}
		}
	}
	mul[0] = cnt[0] = 1;
	for(int Q = Read(); Q ;-- Q)
	{
		int v = Read();
		G[0].emplace_back(v);
		++deg[v];
	}
	for(int i = 0;i <= m;++ i) if(!vis[i]) dfs(i);
	topu();
	for(int i = 1;i <= n;++ i) a[i] = 1ll * a[i] * mul[0] % MOD;
	for(int i = 1;i <= m;++ i)
		if(pos[i]) a[pos[i]] = (a[pos[i]] + 1ll * cnt[i] * add[i]) % MOD;
	for(int i = 1;i <= n;++ i) Put(a[i],' ');
	return 0;
}
posted @ 2021-10-22 11:31  皮皮刘  阅读(53)  评论(0编辑  收藏  举报