P7077 [CSP-S2020] 函数调用

发布时间 2023-10-18 09:29:22作者: 御坂夏铃

显然函数之间的调用关系形成了一张拓扑图,预处理出函数 \(i\) 或其内部所有乘法之积 \(mul_i\)

在调用一个加法函数后调用一个乘法函数,等价于先调用这个乘法函数,然后调用这个加法函数乘数次。所以不妨让乘法函数先做,剩下加法函数产生的贡献只取决于加数和调用次数。这里和线段树的懒标记优先顺序道理相同。

将整个程序视为一个类型 \(3\) 的函数,从其开始拓扑排序。记 \(k_i\) 为位置 \(i\) 当前加上的数之和,\(f_i\) 为函数 \(i\) 内部加法函数的调用次数。

在拓扑排序遇到三种函数时,考虑它们的影响:

  • 类型 \(1\)。此后再也不会调用它了,那么它的贡献即可以算好了:\(k_{P_i}\gets k_{P_i}+V_i\times f_i\)
  • 类型 \(2\)。其贡献在 \(mul\) 数组中,直接忽略。
  • 类型 \(3\)。因为前面的乘法能影响到后面的加法,所以要倒序遍历。若函数 \(i\) 调用了函数 \(j\),那么:\(f_j\gets f_j+f_i,f_i\gets f_i\times mul_j\)

最后位置 \(i\) 的答案即为 \(a_i\times mul_0+k_i\),其中 \(0\) 表示整个程序。注意没被调用过的函数要删掉出边以免影响拓扑排序。