CF626G Raffles
- 有 \(n\) 个奖池,第 \(i\) 个奖池的奖金是 \(p_i\),已经有 \(l_i\) 张彩票押在上面。
- 现在你有 \(t\) 张彩票,你需要将你的彩票分配到这些奖池中,并且保证你在每个奖池中押的彩票数不能超过该奖池原有的彩票数。
- 若你在第 \(i\) 个奖池中押了 \(t_i\) 张彩票,则你中奖的概率为 \(\frac{t_i}{t_i + l_i}\),若你中奖,你可以获得这个奖池的全部奖金 \(p_i\)。
- 一共有 \(q\) 次事件,每次事件会使某个 \(l_i\) 加 \(1\) 或减 \(1\)。
- 你需要在每个事件后求出在最佳方案下你获得的奖金总数的最大期望值。
- \(n,t,q \le 2 \times 10^5\),\(p_i,l_i \le 10^3\),答案精度误差 \(\le 10^{-6}\)。
贪心
划水的时候找的一个 *3100
的题,感觉完全没有 *3100
的难度,想得差不多了结果在实现的时候想岔了,点开题解发现我是 sb,还是题解点快了。
我们可以发现,每次选择贡献的变化量 \(\Delta_i(x) =p_i( \dfrac{x+1}{x+l_i+1}- \dfrac{x}{x + l_i})=p_i\dfrac{l_i}{(x+l_i+1)(x+l_i)}\) 是一个减函数,于是每次选一个数,之后的贡献就会减少,于是我们可以将所有贡献丢到一个堆里面,接着每次暴力取出并更新即可。
至于有修改,可以再维护已经选择的贡献的情况,每次取出贡献最小的彩票,不断替换成贡献最大的彩票。
之前就是这里想岔了,以为复杂度会被卡到 \(\mathcal O(nq)\),于是点开了题解。。
接着发现,因为 \(l_i\) 的变化量是 \(1\),于是最多更新一次。
假设 \(l_i \gets l_i+1\),可以有如下证明,\(l_i \gets l_i - 1\) 类似:
- \(\Delta_i(x) = p_i \dfrac{l_i}{(x + l_i + 1)(x+l_i)}\)
- \(\Delta_i'(x - 1) = p_i \dfrac{l_i+1}{(x + l_i + 1)(x+l_i )}\)
于是,我们可以得到 \(\Delta_i'(x - 1) \ge \Delta_i(x)\),于是可以发现,如果 \(x\) 这个之前在选择方案中,那么被换掉之后, \(x-1\) 不可能继续被换掉。
具体实现的时候,注意要重载 set 的 double 比较函数(虽然好像不重载比较方式也能过)。
本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!