Codeforces 1264C Beautiful Mirrors with queries (概率dp)
队里有人问我这题,我就做了一下,然后就ac了
题意
这个人会从1到n这n个镜子(其中记了若干个checkpoint),他依次问孰与城北徐公美,第\(i\)个镜子回答Yes的概率是\(p_i\),No的概率是\(1-p_i\).如果\(i\)回答了Yes,他就会去问\(i+1\),否则返回去问上一个checkpoint那个镜子。求最后问了镜子n且回答了Yes所需的期望次数。
他会做\(Q\)次更新,每次更新会增加或删除一个checkpoint。保证1永远是一个checkpoint。
\(Q,n\leq 2*10^5\).
解
从概率dp入手:设\(E_i\)为问了前\(i-1\)个镜子,将要问\(i\),距离问完还要的次数的期望。很明显\(E_{n+1}=0\).
显然有递推公式
其中\(c\)是小于等于\(i\)的下标最大的checkpoint。我们把\(n+1\)也看做一个checkpoint。
观察一个checkpoint \(c\),记大于它的最小checkpoint为 \(c'\).
有
于是可以猜测
这个用归纳法应该是随便证的,懒得想了()
于是\(E_c=E_{c'}+\frac{1+p_c+p_cp_{c+1}+...+p_cp_{c+1}...p_{c'-2}}{p_cp_{c+1}...p_{c'-1}}\).
不妨设\(f(c,c')=\frac{1+p_c+p_cp_{c+1}+...+p_cp_{c+1}...p_{c'-2}}{p_cp_{c+1}...p_{c'-1}}\),有\(E_{c}-E_{c'}=f(c,c')\).
记checkpoint序列为一个递增序列\(\{c_1,c_2,...,c_m\}\)
因此\(Ans=E_1=E_1-E_{c_1}+E_{c_1}-E_{c_2}+...+E_{c_m}-E_{n+1}=f(1,c_1)+f(c_1,c_2)+...+f(c_m,n+1)\).
把\(1\)看成\(c_0\),\(n+1\)看成\(c_{m+1}\).分成两种情况讨论更新:
1.\(c_i\)与\(c_{i+1}\)之间插入\(x\).把原来的\(f(c_i,c_{i+1})\)拆成了\(f(c_i,x)\)与\(f(x,c_{i+1})\)两段。
2.删除\(c_i\).把原来的\(f(c_{i-1},c_i)\)与\(f(c_i,c_{i+1})\)合并成\(f(c_{i-1},c_{i+1})\)一段。
很明显\(f(c,c')\)的求值,对\(p\)打个前缀积,再对前缀积打个前缀和就能\(O(1)\)计算。每次更新时查询小于\(x\)的最大值和大于\(x\)的最小值可以直接丢进set里\(O(log\ m)\)搞。因此\(O(Qlog\ n)\)就能过了。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步