PKUWC2018题解

Minimax

\(\mathcal{Link}\)

非常好题。

思路还是很简单的。我们只要求出每个权值最终的概率 \(D_i\) 就行了。考虑怎么在已知两个子节点的情况下求出父节点的答案:

如果节点 \(A\) 含有一组权值为 \(\{a_i\}\) 的点,对应的概率是 \(\{p_{i}\}\);节点 \(B\),相应的,是 \(\{b_i\}\)\(\{q_i\}\)。他们的父节点 \(F\) 以概率 \(P_{max}\) 取较大值。这样,\(A\) 中的某个值最终被取到的概率是 \(P\{A > B\}P_{max}+P\{A<B\}(1-P_{max})\)。也就是说,\(a_i\) 对应概率是 \(p_i(P_{max}\sum_{b_j < a_i}{q_j}+(1-P_{max})\sum_{b_j > a_i}{q_j})\)。注意到这是在原有概率上乘上一个系数的形式。

这个东西当然可以暴力去合并,不过是 T 掉罢了。所以要考虑优化。

我们把 \(F\) 的最终节点按权值从小到大排在数轴上,肯定是产生若干段:一段来自 \(A\),一段来自 \(B\),又一段来自 \(A\)……考虑同一段内部的权值,容易发现,它们共享了相同的系数,因为对于他们来说,另一点内大于他们的权值与小于他们的权值都是一样的。(\(\sum_{b_j < a_i}\) 取到了一样的 \(j\))这启发我们一段一段地计算结果。

到这之后,其实只需要拿一个线段树来实现整段乘系数这件事就好了。因为能够分出不同段的断点一共就 \(n\) 个,而一个断点一旦被合并就不会再产生新段,所以整个合并过程中只出现了 \(n\) 个段。我们用 \(\mathcal{O}(\log n)\) 的时间处理一个段肯定绰绰有余。

具体到实现上来说,有一个优雅的写法:用动态开点线段树维护权值的概率,在两棵线段树上同步遍历,如果有一棵树有而另一棵没有,那么新线段树的这一部分就直接继承;否则递归左右子树,新线段树的这一点就由左右两点 \(\operatorname{pushUp}\) 得到。递归进入左子树的时候,我们把右子树的和传进去,作为更新左子树的系数;反之就把左子树的和传进去,作为更新右子树的系数。比较类似 CDQ 分治或者说整体二分。

AC 代码: