说在前面
我又逊了,为了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;
}