zoukankan      html  css  js  c++  java
  • P7077 [CSP-S2020] 函数调用

    预处理出函数 (i) 乘上的系数 (mul_i),显然函数之间的调用关系形成了一张拓扑图。

    不妨将整个程序视为一个类型 (3) 的函数,从其开始拓扑排序。记 (k_i) 表示位置 (i) 当前加上的数,(f_i) 表示函数 (i) 当前对其中加法函数的调用次数

    注意到一个加法函数产生的贡献只取决于加数调用次数,后者我们可以通过累加的方式来得到;一个

    • 类型 (1)。此后再也不会调用它了,那么它的贡献可以算好了:(k_{P_i}gets k_{P_i}+V_i imes f_i)
    • 类型 (2)。其贡献在 (mul) 中,直接忽略。
    • 类型 (3)。因为前面的乘法能影响到后面的加法,所以考虑倒序遍历。
      函数 (i) 调用了函数 (j)(f_jgets f_j+f_i,f_igets f_i imes mul_j)

    注意没出现过的函数要删掉出边以免影响拓扑排序。时间复杂度 (O(n))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100005
    #define NN 1000005
    #define Mod 998244353
    #define For(i,x,y)for(i=x;i<=(y);i++)
    struct node
    {
    	int next,to;
    }e[2000005];
    bool vis[NN];
    queue<int>que;
    int head[NN],p[NN],val[NN],t[NN],mul[NN],deg[NN],f[NN],a[N],k[N],g;
    int read()
    {
    	int A;
    	bool K;
    	char C;
    	C=A=K=0;
    	while(C<'0'||C>'9')K|=C=='-',C=getchar();
    	while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    	return(K?-A:A);
    }
    inline void add(int u,int v)
    {
    	e[++g].to=v;
    	e[g].next=head[u];
    	head[u]=g;
    }
    void dfs(int u)
    {
    	if(vis[u])return;
    	int v,i;
    	vis[u]=1;
    	if(t[u]==2)mul[u]=val[u];
    	else if(t[u]==3)
    	{
    		mul[u]=1;
    		for(i=head[u];i;i=e[i].next)
    		{
    			v=e[i].to;
    			dfs(v);
    			mul[u]=1LL*mul[u]*mul[v]%Mod;
    		}
    	}
    	else mul[u]=1;
    }
    int main()
    {
    //	freopen("call.in","r",stdin);
    //	freopen("call.out","w",stdout);
    	int n,i,m,c,x,u,v,q;
    	n=read();
    	For(i,1,n)a[i]=read();
    	m=read();
    	For(i,1,m)
    	{
    		t[i]=read();
    		if(t[i]==1)p[i]=read(),val[i]=read();
    		else if(t[i]==2)val[i]=read();
    		else
    		{
    			c=read();
    			while(c--)
    			{
    				x=read();
    				add(i,x);
    				deg[x]++;
    			}
    		}
    	}
    	t[++m]=3;
    	q=read();
    	while(q--)
    	{
    		x=read();
    		add(m,x);
    		deg[x]++;
    	}
    	mul[m]=f[m]=1;
    	dfs(m);
    	For(u,1,m)
    	if(!vis[u])
    	for(i=head[u];i;i=e[i].next)deg[e[i].to]--;
    	que.push(m);
    	while(!que.empty())
    	{
    		u=que.front();
    		que.pop();
    		if(t[u]==1)k[p[u]]=(k[p[u]]+1LL*val[u]*f[u])%Mod;
    		else if(t[u]==3)
    		for(i=head[u];i;i=e[i].next)
    		{
    			v=e[i].to;
    			deg[v]--;
    			if(!deg[v])que.push(v);
    			/*printf("%d %d
    ",u,v);*/
    			f[v]=(f[v]+f[u])%Mod;
    			f[u]=1LL*f[u]*mul[v]%Mod;
    		}
    	}
    	For(i,1,n)printf("%d ",(1LL*a[i]*mul[m]+k[i])%Mod);
    	return 0;
    }
    
  • 相关阅读:
    laravel 5.5 仓库模式 文件之间接口与实现操作
    php 无线分类 根据子级找父级
    php 无限极分类,根据父级 找子级
    laravel5.4 中 dd和dump的区别。
    laravel hash密码生成和密码验证
    oracle建表详细信息
    关于组件的认识
    java的Thread Dump诊断工具
    weblogic连接池
    详解Oracle数据字典
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14989767.html
Copyright © 2011-2022 走看看