• CSP-S2020 T3 函数调用


    CSP-S2020 T3 函数调用

    洛谷评测传送门

    题目描述

    函数是各种编程语言中一项重要的概念,借助函数,我们总可以将复杂的任务分解成一个个相对简单的子任务,直到细化为十分简单的基础操作,从而使代码的组织更加严密、更加有条理。然而,过多的函数调用也会导致额外的开销,影响程序的运行效率。

    某数据库应用程序提供了若干函数用以维护数据。已知这些函数的功能可分为三类:

    1. 将数据中的指定元素加上一个值;
    2. 将数据中的每一个元素乘以一个相同值;
    3. 依次执行若干次函数调用,保证不会出现递归(即不会直接或间接地调用本身)。

    在使用该数据库应用时,用户可一次性输入要调用的函数序列(一个函数可能被调用多次),在依次执行完序列中的函数后,系统中的数据被加以更新。某一天,小 A 在应用该数据库程序处理数据时遇到了困难:由于频繁而低效的函数调用,系统在执行操作时进入了无响应的状态,他只好强制结束了数据库程序。为了计算出正确数据,小 A 查阅了软件的文档,了解到每个函数的具体功能信息,现在他想请你根据这些信息帮他计算出更新后的数据应该是多少。

    输入格式

    第一行一个正整数 nn,表示数据的个数。
    第二行 nn 个整数,第 ii 个整数表示下标为 ii 的数据的初始值为 a_ia**i​。
    第三行一个正整数 mm,表示数据库应用程序提供的函数个数。函数从 1 sim m1∼m 编号。
    接下来 mm 行中,第 jj(1 le j le m1≤jm)行的第一个整数为 T_jT**j​,表示 jj 号函数的类型:

    1. 若 T_j = 1T**j=1,接下来两个整数 P_j, V_jP**j,V**j 分别表示要执行加法的元素的下标及其增加的值;
    2. 若 T_j = 2T**j=2,接下来一个整数 V_jV**j 表示所有元素所乘的值;
    3. 若 T_j = 3T**j=3,接下来一个正整数 C_jC**j 表示 jj 号函数要调用的函数个数,
      随后 C_jC**j​ 个整数 g^{(j)}_1, g^{(j)}2, ldots , g^{(j)}{C_j}g1(j)​,g2(j)​,…,gCj​(j)​ 依次表示其所调用的函数的编号。

    第 m + 4m+4 行一个正整数 QQ,表示输入的函数操作序列长度。
    第 m + 5m+5 行 QQ 个整数 f_if**i​,第 ii 个整数表示第 ii 个执行的函数的编号。

    输出格式

    一行 nn 个用空格隔开的整数,按照下标 1 sim n1∼n 的顺序,分别输出在执行完输入的函数序列后,数据库中每一个元素的值。答案对 oldsymbol{998244353}998244353 取模。


    题解:

    考试之前特意总结的图论模型的抽象。甚至还无限接近正解地压了拓扑序上DP。结果来了一道这样的题,还是不会。

    太菜了。

    考场策略就是个渣渣。本来以为多考了一年能够好一些,结果还是渣渣。甚至还不如第一年去考。

    太菜了。

    太菜了。

    真是太菜了。

    题目中有很多地方暗示了要建图来考虑解决这个问题。比如无递归,就暗示了没有环。比如函数调用。调用的过程就是一张图。比如部分分给的调用关系是一棵树。

    考场上时间真的不够了。这道题甚至都没有细细思考。就直接上手打了最裸的暴力,连线段树架上去优化都没加。真的没有发挥到自己比其他人优秀的地方,光看代码,给人的感觉就是这个人和普及选手甚至0基础没有任何的区别。

    太菜了。

    然后中间过程还爆。讲过多少遍,还是忘记了。

    太菜了。

    真的只是紧张么?

    太菜了。

    总的来说,这道题是一张DAG。这是很显然的。然后我们发现,不能简单地按拓扑序架数据结构。因为这个两种操作和两种操作各自的顺序就让人很迷茫。

    于是考虑加法和乘法之间的转换。可以看出,乘法可以转化成若干次加法。所以对于一次加法,其后面的乘法操作可以转换成加几次来赋给这个加法,作为这个加法的贡献。

    也就是,对于一个加法操作,其贡献是后面所有乘法操作的积。

    对于整张拓扑图进行DP。统计后缀即。至于同一层的顺序问题,在使用链式前向星存储的时候,就是按顺序存的了,所以自然也会按顺序去遍历。

    然后对整张拓扑图DP的时候可以把整张图的遍历顺序用深搜序转成序列问题。这样倒序再来一遍DP。就保证了转移的阶段性,即统计出了所有加法得到的贡献。

    所以:

    #include<cstdio>
    #include<cstring>
    #define int long long
    using namespace std;
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int read()
    {
    	int x=0,gx=1;
    	char ch=nc();
    	while(ch<48||ch>57)
    		if(ch=='-')
    			gx=-1,ch=nc();
    	while(ch>=48&&ch<=57)
    		x=x*10+ch-48,ch=nc();
    	return x*gx;
    }
    const int maxn=1e6+5;
    const int mod=998244353;
    int n,m,q;
    int pos[maxn],val[maxn<<1],id[maxn],opt[maxn<<1],cnt;
    int tot,head[maxn<<1],nxt[maxn<<1],to[maxn<<1],lazy[maxn<<1];
    int gx[maxn],dp[maxn],ans[maxn];
    void add(int x,int y)
    {
    	to[++tot]=y;
    	lazy[tot]=1;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    int dfs(int x)
    {
    	if(~gx[x])
    		return gx[x];
    	if(opt[x]==1)
    		gx[x]=1;
    	else if(opt[x]==2)
    		gx[x]=val[x];
    	else
    	{
    		gx[x]=1;
    		for(int i=head[x];i;i=nxt[i])
    		{
    			lazy[i]=gx[x];
    			gx[x]=(gx[x]*1ll*dfs(to[i]))%mod;
    		}
    	}
    	id[++cnt]=x;
    	return gx[x];
    }
    signed main()
    {
    	n=read();
    	opt[0]=3;
    	for(int i=1;i<=n;i++)
    	{
    		add(0,i);
    		pos[i]=i;
    		val[i]=read();
    		opt[i]=1;
    	}
    	m=read();
    	for(int i=n+1;i<=n+m;i++)
    	{
    		opt[i]=read();
    		if(opt[i]==1)
    			pos[i]=read(),val[i]=read();
    		else if(opt[i]==2)
    			val[i]=read();
    		else
    		{
    			int c=read();
    			while(c--)
    			{
    				int x=read();
    				add(i,x+n);
    			}
    		}
    	}
    	q=read();
    	for(int i=1;i<=q;i++)
    	{
    		int x=read();
    		add(0,x+n);
    	}
    	memset(gx,-1,sizeof(gx));
    	dfs(0);
    	dp[0]=1;
    	for(int i=cnt;i>=1;i--)
    	{
    		int x=id[i];
    		for(int j=head[x];j;j=nxt[j])
    		{
    			int y=to[j];
    			dp[y]=(dp[y]+dp[x]*1ll*lazy[j])%mod;
    		}
    		if(opt[x]==1)
    			ans[pos[x]]=(ans[pos[x]]+dp[x]*1ll*val[x])%mod;
    	}
    	for(int i=1;i<=n;i++)
    		printf("%lld ",ans[i]);
    	puts("");
    	return 0;
    }
    
    
  • 相关阅读:
    H5,JS国际化网站中英文切换
    DIV右上角标签的CSS3实现技巧
    .NET Core也是国产化信息系统开发的重要选项
    微软自家的.Net下的JavaScript引擎--- ClearScript
    Java 生态碎片化 和 .NET生态的一致性
    使用 .NET 进行游戏开发
    .NET 是信息技术应用创新产业重要参与者
    Chrome 80+ 跨域Samesite 导致的cookie not found 解决方法
    在腾讯云云函数计算上部署.NET Core 3.1
    腾讯云 云开发 部署 Blazor网站
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13952706.html
Copyright © 2020-2023  润新知