給出一個數組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個子節點也很簡單
同時修改操做成了單點修改啦
這樣子就能夠過了