トピックリンク
\(まず\) 、はじめに
この質問は黒偽のタイトル・トラックであります
I Aの前に学校の兄弟のグループは、私があまりにも弱かったです
私たちの考えはの首長から派生する必要がありますczpcf
その式は非常に性急な推進している自己と思います
だから私は別のものを書くことにしました
\(第二\) 、アイデア
定義\(F(i、j)は \) カジノから(私は\)\カジノで始まる\は(私は\)カジノで勝つ\(J \)優勝と終了の確率を
定義\(F(J + 1、 k)は\) カジノから\(J \) + 1は、カジノで始まる\(J \)カジノで+ 1勝\(K \)を受賞し、終了する確率
定義された\(G(i、j)は \) と\(F \)が、逆に
だから、\(F(I、K)\) =直接過去の確率(ここでは真ん中にもラップを回しませんが、決して持っていたかもしれ行く\(J \を))+サークルの真ん中順番にをし、確率(円の真ん中に渡りました\(J \) )
行く直接過去の確率= \(F(I、J)* F(J + 1、k)は\)
円の中央ターンにおける確率を越えて行く= \(F(I、J)* F(J + 1、K)\) * \(\ DisplayStyle \ SUM ^ {+ \ inftyの} _ {P = 1} W ^ P \)
前記\(W \)は、中間革命の確率で
フォーカスがされて(\ w)は\カウントする方法
\(W \) = \((1-F(j + 1、k))を(1-G(i、j)の)\)
この式は、それが来る方法ですか?
ことを理解すべきで\(1-F(j + 1、k)が\)
カジノから\(J \)カジノで始まる+ 1 \(J \)カジノで+ 1勝\(K \)を受賞し、終了する確率
ここでは\(1-F(J + 1、k)は\)
カジノ\(J \) + 1は、デフォルトの開始であります
唯一の条件
1:カジノで\(J \) + 1勝
2:カジノで\(K \)勝利
2中の少なくとも一つが満たされていません
しかし、エンドに\(2 \)の結果は、右の間隔(関係なく、彼女のから復帰する予定です\([J + 1、K ] \) どのように多くの周回ターン)
\(さらに\) 、簡素化
\ [F(I、K)\]
\ [^ Pの\ W = F(i、j)はF *(J + 1、K)\ displaystyle \和^ {+ \ inftyの} _ {P = 1}]
\ [= F(i、j)はF *(J + 1、K)\ FRAC {1-W ^ {+ \ inftyの}} {1-W} \]
\ [^ {A + \ inftyの} = 0 \]
\ [\ RIGHTARROW = \ FRAC {F(i、j)はF *(J + 1、K)}、{1-(1-F(j + 1、k))を(1-G(i、j)は)} \]
この時間は、ツリーラインを維持するために使用することができます
\(結局\) 、\(コード\)
#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define reg register int
#define isdigit(x) ('0' <= (x)&&(x) <= '9')
template<typename T>
inline T Read(T Type)
{
T x = 0,f = 1;
char a = getchar();
while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();}
while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();}
return x * f;
}
#define fi first
#define se second
typedef double db;
const int MAXN = 100010;
db p[MAXN];
struct node
{
double g,f;
}tree[MAXN << 2];
inline void sum(db &f,db &g,db f1,db f2,db g1,db g2)
{
f = f1 * f2 / (1 - (1 - f2) * (1 - g1));
g = g1 * g2 / (1 - (1 - f2) * (1 - g1));
}
inline void BuildTree(int k,int l,int r)
{
if(l == r)
{
tree[k].f = p[l],tree[k].g = 1 - p[l];
return;
}
int mid = l + r >> 1;
BuildTree(k << 1,l,mid);
BuildTree(k << 1 | 1,mid + 1,r);
sum(tree[k].f,tree[k].g,tree[k << 1].f,tree[k << 1 | 1].f,tree[k << 1].g,tree[k << 1 | 1].g);
}
inline pair<db,db> query(int k,int l,int r,int L,int R)
{
if(L <= l&&r <= R) return make_pair(tree[k].f,tree[k].g);
int mid = l + r >> 1;
pair<db,db> k1,k2;k1.fi = k2.fi = k1.se = k2.se = 1;
if(L <= mid) k1 = query(k << 1,l,mid,L,R);
if(mid < R) k2 = query(k << 1 | 1,mid + 1,r,L,R);
db T1,T2;
sum(T1,T2,k1.fi,k2.fi,k1.se,k2.se);
return make_pair(T1,T2);
}
inline void update(int k,int l,int r,int pos,db x)
{
if(l == r)
{
tree[k].f = x,tree[k].g = 1 - x;
return;
}
int mid = l + r >> 1;
if(pos <= mid) update(k << 1,l,mid,pos,x);
else update(k << 1 | 1,mid + 1,r,pos,x);
sum(tree[k].f,tree[k].g,tree[k << 1].f,tree[k << 1 | 1].f,tree[k << 1].g,tree[k << 1 | 1].g);
}
int main()
{
int n = Read(1),q = Read(1);
for(reg i = 1;i <= n;i++)
{
int a = Read(1),b = Read(1);
p[i] = (db)a / b;
}
BuildTree(1,1,n);
while(q--)
{
int sit = Read(1);
if(sit & 1)
{
int pos = Read(1),a = Read(1),b = Read(1);
update(1,1,n,pos,((db)a / b));
} else {
int l = Read(1),r = Read(1);
cout << query(1,1,n,l,r).fi << endl;
}
}
return 0;
}