函数调用

P7077 [CSP-S2020] 函数调用

我们考虑如果没有第三种函数,如何解决这个问题。

发现,对于每个1(1类),我们考虑在它之后执行了多少个2,然后累乘,就是这个增加操作实际的贡献。我们只需要倒序,维护一个后缀积即可。

我们的核心思想就是计算每个1的贡献是几倍。

考虑有3会怎么样。还是延续上面的思路。有3,那么可以递归调用,我们记 \(mul_i\) 表示执行这个函数后,整个序列会而且恰好是DAG,我们发现母结点的乘积恰好等于自己的乘积 \(\times\) 所有后继乘积,可以用拓扑排序的逆序求解。

然后我们就要求解每个函数会被调用的次数了。我们发现母结点被调用一次,那么子节点就会相对应的调用多次(每次当母结点被调用一次,子节点调用次数是一样的)。我们先倒着求出所有第一层的函数调用的次数(即没有操作3的情况)。对于不在第一层的点,我们发现它的调用次数首先有一个基数 \(sum_{fa}\),然后对于它所有的兄弟节点,需要乘上在它之后的 \(mul_{brother}\)。这个处理是拓扑排序的正序。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
typedef long long ll;

const int N=100010,M=1000010,mod=998244353;
int n,w[N],m,d[N],q[N],g[N];
int h[N],e[M],ne[M],idx;//don't forget memset h!
void add(int a,int b){
    ++d[b],e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

struct Func{
    int t,p,v,mul,sum;
}f[N];
void topo(){
    int hh=0,tt=-1;
    E(i, m)
        if(!d[i])q[++tt]=i;
    Wh(hh<=tt){
        int x=q[hh++];
        Ed{
            int j=e[i];
            if(--d[j]==0)q[++tt]=j;
        }
    }
}
void calc_mul(){
    Re(i, m-1, 0){
        int x=q[i];
        Ed{
            int j=e[i];
            f[x].mul=1ll*f[x].mul*f[j].mul%mod;
        }
    }
}
void calc_sum(){
    L(i, m){
        int x=q[i];
        ll sum=f[x].sum;
        Ed{
            int j=e[i];
            f[j].sum=(f[j].sum+sum)%mod;
            sum=sum*f[j].mul%mod;
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    E(i, n)cin>>w[i];
    cin>>m;
    memset(h,-1,m*4+4);
    E(i, m){
        cin>>f[i].t;
        if(f[i].t==1)cin>>f[i].p>>f[i].v;
        else if(f[i].t==2)cin>>f[i].mul;
        else{
            int c;
            cin>>c;
            W(c){
                int x;
                cin>>x;
                add(i,x);
            }
        }
    }
    topo();
    E(i, m)
        if(f[i].t!=2)f[i].mul=1;
    calc_mul();
    int q;
    cin>>q;
    ll mul=1;
    E(i, q)cin>>g[i];
    Re(i, q, 1){
        int x=g[i];
        f[x].sum=(f[x].sum+mul)%mod;
        mul=mul*f[x].mul%mod;
    }
    calc_sum();
    E(i, n)w[i]=w[i]*mul%mod;
    E(i, m)
        if(f[i].t==1)w[f[i].p]=(w[f[i].p]+1ll*f[i].sum*f[i].v%mod)%mod;
    E(i, n)cout<<w[i]<<' ';
    return 0;
}
posted @ 2023-10-09 13:52  wscqwq  阅读(5)  评论(0编辑  收藏  举报