cpdeforces 712 E. Memory and Casinos 几率论 + 线段树

给出一个数组p,长度为n,1  <= n  <= 10^5数组

表示有n个格子,在第i个格子,你有p[i]的几率会到i + 1,有1 - p[i]的几率会到i - 1spa

若是在区间[l,r]上玩游戏,咱们规定你起点在l,而后你开始走,游戏

若是你到了l - 1,那么你失败了,游戏结束query

若是你到了r + 1,那么你成功了,游戏结束

如今有q个操做,1 <= q <= 10^5

1 i a b   修改p[i] = (double)a / b

2 l r      询问在[l,r]上玩游戏,成功的几率

 

看这道题目,咱们首先反应就是线段树,那要维护什么?

咱们先来看看在[l,r]上玩游戏,

令f(i)表示从i开始,到r + 1的几率,即游戏成功的几率

咱们要求的就是f(l)

显然,f(l - 1) = 0,f(r + 1) = 1

对l <= i <= r,f(i) = p[i] * f(i + 1) + (1 - p[i]) * f(i - 1)

则 f(i) - f(i - 1) = p[i] * f(i + 1) - p[i] * f(i - 1)

令g(i) = f(i) - f(i - 1)

(咱们要求f(l),因为g(l) = f(l) - f(l - 1) = f(l),因此咱们要求的变成了g(l))

则g(i) = p[i] * (g(i + 1) + g(i))

令u[i] - (1 - p[i]) / p[i]

则g(i + 1) = u[i] * g(i)

发现g(l) + g(l + 1) + ... + g(r + 1) = 1

即g(l) = 1 / (1 + u[l] + u[l] * u[l + 1] + ... + u[l] * u[l + 1] * ... * u[r] )

因此,若是咱们用一颗线段树,叶子节点i的值前缀积u[1] * u[2] * .. * u[i]

而后维护区间和

那么对于每个询问[l,r],要求g(l)

若是l = 1,g(l) = 1 / (1 + query(1,r,1,n,1))

若是l > 1,g(l) = query(l-1,l-1,1,n,1) / query(l-1,r,1,n,1)

而后修改操做在这里就是区间修改了

能够了

可是,这样子会被卡精度,我就被卡了

怎么改:

线段树维护2个值,

若是一个节点表明的区间是[l,r]那么这个节点维护

u[l] + u[l] * u[l + 1] + ... + u[l] * ... * u[r]  和

u[l] * ... * u[r]

那么合并2个子节点也很简单

同时修改操做成了单点修改啦

这样子就能够过了

相关文章
相关标签/搜索