首页 > 其他分享 >P7077 [CSP-S2020] 函数调用 题解

P7077 [CSP-S2020] 函数调用 题解

时间:2022-10-13 15:57:41浏览次数:75  
标签:cnt ch int 题解 函数调用 MAXN 操作 P7077 倒序

首先考虑没有 3 操作的情况,显然有线段树的 \(O(n\log n)\) 做法,但是另外有一种 \(O(n)\) 做法:因为 2 操作是全局乘所以我们完全可以统计出全局乘了多少然后直接往 \(a_i\) 上乘,至于 1 操作,其加上的数会受到其后面的 2 操作的影响但是前面的不会,据此考虑倒序处理,对于每一个 1 操作我们算出后面 2 操作总共乘了多少就知道这个 1 操作到底对指定位置有多少贡献。

现在考虑加入 3 操作的影响,注意到如果 3 操作向其调用的函数连边那么函数关系会构成一张 DAG,对于指定的 \(q\) 个调用操作,建立超源 0 向其连单向边,考虑在反向图上使用一次拓扑排序求出每个操作执行之后每个点会使得全局乘上多少数,记作 \(Mul_x\)。

接下来考虑在正向图上做一次拓扑排序求出每个 1 操作最后会被乘多少次,设 \(cnt_x\) 表示当前操作会被乘多少次(注意 \(cnt_x\) 只对 1 操作有意义,但是每个点都需要记录以保证正确转移,初值 \(cnt_0=1\) 别的都是 0),注意到每一个操作只会被在其后面的所有 2 操作影响,所以我们需要倒序遍历每个 3 操作的操作序列,比如说如果一个 3 操作调用序列为 2 3 4 那么这次拓扑排序需要以 4 3 2 的顺序遍历,这样才能保证倒序处理,考虑记录一个 \(tag\) 表示倒序遍历时总共乘了多少也就是当前 3 操作内部乘上了多少,这样可以直接记录到前面操作的 \(cnt\) 上,至于整个 3 操作后面对当前 1 操作的贡献,直接从 3 操作往下传即可。

Code:

/*
========= Plozia =========
	Author:Plozia
	Problem:P7077 [CSP-S2020] 函数调用
	Date:2022/10/12
========= Plozia =========
*/

#include <bits/stdc++.h>
typedef long long LL;
using std::queue;

const int MAXN = 1e5 + 5, MAXM = 1e6 + 5;
const LL P = 998244353;
int n, m, opt[MAXN], pos[MAXN], q, d[MAXN];
LL Mul[MAXN], a[MAXN], val[MAXN], cnt[MAXN];
struct Graph
{
	int Head[MAXN], cntEdge, In[MAXN]; struct node { int To, Next; } Edge[MAXM + MAXN];
	void add(int x, int y) { ++cntEdge; Edge[cntEdge] = (node){y, Head[x]}; Head[x] = cntEdge; }
}og, rg;

int Read()
{
	int sum = 0, fh = 1; char ch = getchar();
	for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
	return sum * fh;
}

void Topsort1()
{
	queue <int> q; for (int i = 0; i <= m; ++i) if (rg.In[i] == 0) q.push(i);
	while (!q.empty())
	{
		int x = q.front(); q.pop();
		for (int i = rg.Head[x]; i; i = rg.Edge[i].Next)
		{
			int u = rg.Edge[i].To; --rg.In[u]; if (rg.In[u] == 0) q.push(u);
			Mul[u] = Mul[u] * Mul[x] % P;
		}
	}
}
void Topsort2()
{
	queue <int> q; for (int i = 0; i <= m; ++i) if (og.In[i] == 0) q.push(i);
	while (!q.empty())
	{
		int x = q.front(); q.pop(); LL tag = 1;
		for (int i = og.Head[x]; i; i = og.Edge[i].Next)
		{
			int u = og.Edge[i].To; --og.In[u]; if (og.In[u] == 0) q.push(u);
			cnt[u] = (cnt[u] + cnt[x] * tag % P) % P; tag = tag * Mul[u] % P;
		}
	}
}

int main()
{
	n = Read(); for (int i = 1; i <= n; ++i) a[i] = Read();
	m = Read(); Mul[0] = cnt[0] = 1;
	for (int i = 1; i <= m; ++i)
	{
		opt[i] = Read(); Mul[i] = 1;
		if (opt[i] == 1) { pos[i] = Read(), val[i] = Read(); }
		if (opt[i] == 2) { Mul[i] = Read(); }
		if (opt[i] == 3)
		{
			int k = Read();
			for (int j = 1; j <= k; ++j) { int tmp = Read(); og.add(i, tmp); rg.add(tmp, i); ++og.In[tmp]; ++rg.In[i]; }
		}
	}
	q = Read(); for (int i = 1; i <= q; ++i) d[i] = Read();
	for (int i = 1; i <= q; ++i) { og.add(0, d[i]); rg.add(d[i], 0); ++og.In[d[i]]; ++rg.In[0]; }
	Topsort1(); Topsort2();
	for (int i = 1; i <= n; ++i) a[i] = a[i] * Mul[0] % P;
	for (int i = 1; i <= m; ++i)
		if (opt[i] == 1) a[pos[i]] = (a[pos[i]] + cnt[i] * val[i] % P) % P;
	for (int i = 1; i <= n; ++i) printf("%lld%c", a[i], " \n"[i == n]); return 0;
}

标签:cnt,ch,int,题解,函数调用,MAXN,操作,P7077,倒序
From: https://www.cnblogs.com/Plozia/p/16788400.html

相关文章

  • QT QSS样式部分控件生效问题解决记录
    在窗口复杂的时候,建议设置QSS函数setStyleSheet放到 ui->setupUi(this);之前,比如:MainWindow{QFilefile(":/css/TeachingNeedleCard_style.qss");file.op......
  • CF436E Cardboard Box 题解
    CF436ECardboardBox\(n\)个关卡,对每个关卡,你可以花\(a_i\)代价得到一颗星,也可以花\(b_i\)代价得到两颗星,也可以不玩。问获得\(m\)颗星最少需要多少时间。给一......
  • CF1217F 题解
    传送门题意给定一个\(n\)个点的无向图,最初图中无边。两种操作:1xy若\(x,y\)中有边,则删去;否则加入。2xy询问\(x,y\)是否连通。\(x,y\)均加密,真实的\(x,......
  • LG-P3550 [POI2013]TAK-Taxis 题解
    LG-P3550[POI2013]TAK-TaxisSolution目录LG-P3550[POI2013]TAK-TaxisSolution更好的阅读体验戳此进入题面输入格式SolutionCodeUPD更好的阅读体验戳此进入题面存在......
  • 关于一个人类智慧的DP - Vijos 1037 搭建双塔 题解
    关于一个人类智慧的DP-Vijos1037搭建双塔目录关于一个人类智慧的DP-Vijos1037搭建双塔更好的阅读体验戳此进入题面输入格式ExamplesSolutionCodeCode-C++98(JDO......
  • LG-P3552 [POI2013]SPA-Walk 题解
    LG-P3552[POI2013]SPA-WalkSolution目录LG-P3552[POI2013]SPA-WalkSolution更好的阅读体验戳此进入题面输入格式SolutionCodeUPD更好的阅读体验戳此进入(建议您从上......
  • P8298 [COCI2012-2013#2] POPUST 题解
    题目题目大意有\(N\)种饭菜,每种饭菜有两种价格\(A_i\)和\(B_i\)。对于两种价格,如果你的选的第一道菜是\(i\),则它的价格为\(A_i\)否则为\(B_i\),求对于点\([......
  • tiktok黑屏问题解决方法
    最近很多刚玩tiktok的朋友反馈tiktok黑屏的问题,其实,tiktok黑屏的问题主要是因为官方限制国内用户大量发布低质量搬运视频的风控方式之一,今天来做一期解决tiktok黑屏的方......
  • MAC上cocoscreator2.4.3打包Android出现ABIs [armeabi] are not supported for platfo
    打开vip_kingdom_rush_2游戏工程,点击构造发布,打开EditorWindow,选择发布平台为Android,构建成功后,点击编译 如果编译出现下面错误为armeabi架构不支持,在gradle.propertie......
  • <一>从汇编指令角度看形参带默认值的函数调用
    下面代码中备注部分为从汇编指令角度看形参带默认值得函数调用点击查看代码#include<iostream>usingnamespacestd;intsum(inta=10,intb=20){ returna+b; ......