给出一个数组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个子节点也很简单
同时修改操做成了单点修改啦
这样子就能够过了