• P7077 函数调用(call)


    说在前面

    我又逊了,为了T1我T3都没开...

    题意简述

    (n)个数,为(a_1,a_2,cdots a_n)。有(m)个函数,每个函数可以如一下方式表示:

    • (T_i = 1)时,(P_i,V_i) (a_{P_i} leftarrow a_{P_i} + V_i)
    • (T_i = 2)时,(V_i) 所有数乘上(V_i)
    • (T_i = 3)时,(C_i,g_i^{(1)},g_{i}^{(2)},cdots g_{i}^{(C_i)}),表示调用这些函数,保证不出现环。

    数据范围不想写了,/kk

    简单口胡

    u1s1,这题还是有一点意思的。
    暴力:线段树

    正解:

    先考虑没有(T_i = 3)的时候怎么做。

    我分别调用((T_i = 1,P_i = 1,V_i = 1),(T_i = 2,V_i = 2),(T_i = 1,P_i = 2,V_i = 2),(T_i = 2,V_i = 3))这几个鬼函数。

    显然,如果我进行一个(T_i = 2)的操作,那么前面所有(T_i = 1)的操作所给(a_{P_i})带来的贡献(也就是(V_i))要翻(V_i)(T_i = 2)(V_i))倍。

    换个角度,考虑每个(T_i = 1)的函数会被翻几倍,很容易想到后缀积。具体地,设(add_i)(i)函数被调用个数(翻的倍数),则易得

    [add_i = prod_{k = i + 1} ^ n V_k[T_k = 2] ]

    然后更新既珂。

    转移到有(T_i = 3),显然是一个( ext{DAG})图,那么先拓扑,将先后关系整一下,然后:

    (mul_i)为调用(i)后所乘的总积。

    [mul_i =mul_i imes prod_{k in exttt{son}_i} mul_k\ ]

    (add_i)求法有点不同,在我们处理到(x)时,去更新其子节点(v)

    [add_{v_i} = add_{v_i} + add_x imes prod_{k = i + 1} ^ { exttt{size}} mul_{v_k} ]

    于是这题没了。

    注意求(add)时,注意调用先后顺序,一定是调用先的在前。

    # include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 2;
    const long long mod = 998244353;
    int n,m,q;
    int F[N];
    long long a[N];
    long long mul[N],add[N],V[N];
    int T[N],P[N];
    int du[N],que[N];
    vector <int> g[N];
    
    template <typename T> void read(T &x)
    {
        x = 0;
        int w = 1;
        char ch = getchar();
        while(!isdigit(ch))
        {
            if(ch == '-') w = -1;
            ch = getchar();
        }
        while(isdigit(ch))
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        x *= w;
        return;
    }
    
    void topsort(void)
    {
        int cur = 0;
        queue <int> q;
        for(int i = 1; i <= m; i++)
        {
            if(!du[i]) q.push(i);
        }
        while(!q.empty())
        {
            int x = q.front();q.pop();
            que[++cur] = x;
            for(int i = 0; i < g[x].size(); i++)
            {
                int v = g[x][i];
                    if(--du[v] == 0) 
                    {
                        q.push(v);
                    }
            }
        }
        return;
    }
    
    void Get1(void)
    {
        for(int i = m; i >= 1; i--)
        {
            int x = que[i];
            // printf("x = %d
    ",x);
            for(int j = 0; j < g[x].size(); j++)
            {
                int v = g[x][j];
                mul[x] = (mul[x] * mul[v]) % mod;
                // printf("mul[%d] = %lld
    ",x,mul[x]);
            }
        }
        return;
    }
    
    void Get2(void)
    {
        long long cur = 1;
        for(int i = 1; i <= m; i++)
        {
            int x =que[i];
            cur = 1;
            for(int j = g[x].size() - 1; j >= 0; j--)
            {
                int v = g[x][j];
                add[v] = (add[v] + add[x] * cur) % mod;
                cur = (cur * mul[v]) % mod;
            }
        }
        return;
    }
    
    int main(void)
    {
        read(n);
        for(int i = 1; i <= n; i++)
        {
            read(a[i]);
        }
        read(m);
        for(int i = 1; i <= m; i++)
        {
            read(T[i]);
            if(T[i] == 1)
            {
                read(P[i]),read(V[i]);
                mul[i] = 1;
            }
            else
            {
                if(T[i] == 2)
                {
                    read(V[i]);
                    mul[i] = V[i];
                }
                else
                {
                    mul[i] = 1;
                    int c;
                    read(c);
                    for(int j = 1; j <= c; j++)
                    {
                        int v;
                        read(v);
                        g[i].push_back(v);
                        du[v]++;
                    }
                }
            }
        }
        topsort();
        Get1();
        read(q);
        for(int i = 1; i <= q; i++) read(F[i]);
        long long cur = 1;
        for(int i = q; i >= 1; i--)
        {
            add[F[i]] = (add[F[i]] + cur) % mod;
            cur = (cur * mul[F[i]]) % mod;
        }
        Get2();
        for(int i = 1; i <= n; i++) a[i] = (a[i] * cur) % mod;
        // for(int i = 1; i <= m; i++)
        // {
        //     printf("add[%d] = %lld
    ",i,add[i]);
        // }
        for(int i = 1; i <= m; i++)
        {
            if(T[i] == 1)
            {
                a[P[i]] = (a[P[i]] + V[i] * add[i] % mod) % mod;
            }
        }
        for(int i = 1; i <= n; i++)
        {
            printf("%lld ",a[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    数据库函数
    数据库查询习题整理(二)
    数据库查询习题整理(一)
    1202数据库查询
    1201新课程TSQL语句
    1123项目第五天
    1121项目第四天
    1120项目第三天
    14
    にちかん
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/P7077.html
Copyright © 2020-2023  润新知