显然函数之间的调用关系形成了一张拓扑图,预处理出函数 \(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\) 表示整个程序。注意没被调用过的函数要删掉出边以免影响拓扑排序。
标签:调用,函数,函数调用,加法,mul,P7077,gets,CSP,乘法 From: https://www.cnblogs.com/landsol/p/17771301.html