• [CSP-S-2 2020 T3] 函数调用 (拓扑排序)


    [CSP-S 2020 T3] 函数调用 (拓扑排序)

    updated: 之前标题好像搞成T2的标题了。。

    很难考虑每个操作的顺序,但由于操作比较简单,可以直接考虑每个操作贡献的权值

    一个操作的权值可以定义为:每次这个操作执行之后后,后面所有的乘法操作的积

    如果没有递归,只需要倒序枚举一次调用情况,就能知道所有的权值

    对于递归的情况,显然函数之间的递归关系构成一张拓扑图,可以考虑预处理出每个操作的乘法操作之积

    对于所有的函数,同样能得到一个权值,接下来的操作只需要把每个存在递归的函数不断将权值向下传给子函数

    如果把最终的调用序列看做一个主函数,那么对于这个操作实际也是一样的做法

    即:倒序枚举一次累积,然后乘上自己的权值下传即可

    Tips: 最后加入贡献时,注意先将所有数的权值乘上全局乘法倍数,然后再依次处理每个加法操作

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    int rd(){ 
    	int s=0,f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=1e5+10,P=998244353;
    
    int n,m;
    int A[N],T[N],H[N]; 
    // A为原数组,T为乘法积,H为函数调用权值
    int O[N],X[N],Y[N];
    int B[N*11],C,L[N],R[N],ind[N];
    int Q[N],QL,QR;
    
    int main() {
    	//freopen("call.in","r",stdin),freopen("call.out","w",stdout);
    	rep(i,1,n=rd()) A[i]=rd();
    	m=rd()+1; // 令m+1号为主函数
    	rep(i,1,m) {
    		O[i]=i<m?rd():3,T[i]=1;
    		if(O[i]==1) X[i]=rd(),Y[i]=rd();
    		else if(O[i]==2) T[i]=rd();
    		else {
    			L[i]=C+1,R[i]=C+=rd();
    			rep(j,L[i],R[i]) ind[B[j]=rd()]++;
    		}
    	}
    	rep(i,QL=1,m) if(!ind[i]) Q[++QR]=i;
    	while(QL<=QR) {
    		int u=Q[QL++];
    		if(O[u]==3) rep(j,L[u],R[u]) if(--ind[B[j]]==0) Q[++QR]=B[j];
    	}
    	drep(k,m,1){
    		int u=Q[k];
    		if(O[u]==3) rep(j,L[u],R[u]) T[u]=1ll*T[u]*T[B[j]]%P;
    	}
    	
    	rep(i,H[m]=1,n) A[i]=1ll*A[i]*T[m]%P;
    	rep(k,1,m) {
    		int u=Q[k],x=1;
    		drep(j,R[u],L[u]){
    			int v=B[j];
    			H[v]=(H[v]+1ll*x*H[u])%P;
    			x=1ll*x*T[v]%P;
    		}
    		if(O[u]==1) A[X[u]]=(A[X[u]]+1ll*H[u]*Y[u])%P;
    	}
    	rep(i,1,n) printf("%d ",A[i]); puts("");
    }
    
  • 相关阅读:
    git连接到https服务器时出现“gnutls_handshake() failed”
    Linux内核:通知链 机制
    在Linux驱动中使用notifier通知链
    Linux 内核:RCU机制与使用
    什么是工程师文化?
    在Android源码中查找Java代码中native函数对应的C++实现
    Windows下Qt5程序打包发布
    Android Framework:如何让 App 拿到Power key 值
    Windows 监控小工具
    Windows 远程桌面无法上传文件或者文件夹
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13944599.html
Copyright © 2020-2023  润新知