zoukankan      html  css  js  c++  java
  • CSP-S T3 函数调用

    事先声明,考试时由于本人太菜,T1写了两个小时还tm没判12.31挂了所以只是口胡了个拓扑排序,直接打了40分,考完自闭了很久之后才码出来

    首先我们发现由于不会递归,所以把所有操作连起来会形成一张DAG,DAG上并没有什么很好的数据结构可以维护,所以可以考虑分别考虑乘法和加法的影响,可以发现,最终值是初始值乘以一堆值再加上一堆值

    又因为乘法显然会对加法产生影响所以可以考虑,每个加法到最后都会加几次

    可以发现每个加法最后加几次,等价于在这个加法之后,全局乘的数值的积,于是我们可以考虑倒着处理这个函数数列

    每次加法的时候就加上标记,(前面乘的积),乘法就更新全局积,如果是递归,就先给它下辖(即最终会被调用的乘法或者加法)的所有加法加上标记(打在它本身上面,最终拓扑排序下传),然后再用下面的乘法更新全局积

    最后打完标记最后拓扑排序下传一下就行.具体地依然从后往前处理,注意要更新一下最终加法的次数(类似于线段树合并,处理右儿子时要考虑左儿子的贡献),具体看代码吧

    其实也不是很难,还是我太菜了

    /*call*/
    #include<bits/stdc++.h>
    using namespace std;
    int read(){
        char c = getchar();
        int x = 0;
        while(c < '0' || c > '9')        c = getchar();
        while(c >= '0' && c <= '9')        x = x * 10 + c - 48,c = getchar();
        return x;
    }
    const int maxn = 1e6 + 10;
    struct Edge{
        int nxt,point;
    }edge[maxn<<1];
    int a[maxn];
    int head[maxn],tot;
    int deg[maxn];
    void add_edge(int x,int y){
        edge[++tot].nxt = head[x];
        edge[tot].point = y;
        head[x] = tot;
        deg[y]++;
    }
    struct Func{
        int op;
        int p,v;
    }f[maxn];
    int seq[maxn];
    int C = 1;
    int tag[maxn];
    #define mod 998244353
    int mul[maxn];
    void add(int &x,int y){
        x += y - mod;
        x += (x >> 31) & mod;
    }
    void sol(int x){
        if(f[x].op == 1){
            add(tag[f[x].p],1ll * C * f[x].v % mod) ;
            return;
        }
        else if(f[x].op == 2){
            C = 1ll * C * f[x].v % mod;
        }
        else{
            for(int i = head[x]; i; i = edge[i].nxt){
                sol(edge[i].point);
            }
        }
    }
    void dfs(int x){
        if(~mul[x])    return;
        mul[x] = 1;
        if(f[x].op == 1)    return;
        if(f[x].op == 2){
            mul[x] = f[x].v;
            return;
        }
        for(int i = head[x]; i ; i = edge[i].nxt)        dfs(edge[i].point),mul[x] = 1ll * mul[x] * mul[edge[i].point] % mod;
    }
    int q[maxn];
    int main(){
        int n = read();
        for(int i = 1; i <= n; ++i)        a[i] = read();
        int m = read();
        for(int i = 1; i <= m; ++i){
            int op = read();
            f[i].op = op;
            if(op == 1){
                f[i].p = read(),f[i].v = read();
            }
            else if(op == 2){
                f[i].v = read();
            }
            else{
                int s = read();
                for(int j = 1; j <= s; ++j){
                    int x = read();
                    add_edge(i,x);
                }
            }
        }
        memset(mul,-1,sizeof(mul));
        int t = read();
        for(int i = 1; i <= t; ++i)        seq[i] = read();
        for(int i = 1; i <= m; ++i)        dfs(i); 
        for(int x = t; x; --x){
            if(f[seq[x]].op == 1)        add(tag[seq[x]],C);
            if(f[seq[x]].op == 2)        C = 1ll * C * f[seq[x]].v % mod;
            if(f[seq[x]].op == 3){
                add(tag[seq[x]],C);
                C = 1ll * C * mul[seq[x]] % mod;
            }
        }
        for(int i = 1; i <= n; ++i)        a[i] = 1ll * a[i] * C % mod;
        int l = 1,r = 0;
        for(int i = 1; i <= m; ++i)        if(!deg[i])        q[++r] = i;
        while(l <= r){
            int x = q[l++];
            if(f[x].op == 1){
                add(a[f[x].p],1ll * tag[x] * f[x].v % mod);
                continue;
            }
            if(f[x].op == 2)    continue;
            int v = 1;
            for(int i = head[x]; i ; i = edge[i].nxt){
                int y = edge[i].point;
                add(tag[y],1ll * tag[x] * v % mod);
                --deg[y];if(!deg[y])    q[++r] = y;
                v = 1ll * v * mul[y] % mod;
            }
        }
        for(int i = 1; i <= n; ++i)        printf("%d%c",a[i]," 
    "[i == n]);
        return 0;
    }
  • 相关阅读:
    K-Means++ 聚类之数据可视化:使用gnuplot
    QQ设计第1-5步
    QQ设计第1-5步
    为什么有很深的windows基础还是不能动摇linux半步
    常用命令
    在线会计_金蝶友商网
    XP使用VNC远程桌面CentOS 6
    Fatal error: Call to undefined function mb_substr()
    如何汉化 po 文件及编译成 mo 文件
    idoerp
  • 原文地址:https://www.cnblogs.com/y-dove/p/13948175.html
Copyright © 2011-2022 走看看