[CF712E] Memory and Casinos (mathematical expectation DP)

Topic Link

main idea

Given a sequence, when you are in a certain point, there is a probability to go right \ (P_i \) (left to \ (1-P_i \) ),
gives \ (M \) operations, there are operations two categories:

1 XYZ: the \ (p_x \) values for the modified \ (\ FRAC the Y} {} {the Z \)
2 the LR: Ask your from \ (L \) starting random walk, without passing through \ (L-1 ) \ reaches the lower case \ (R + 1 \) probability

Thinking

We provided for a range of two values \ (Vall, ValR \) ,
respectively, represent the probability to win the starting point from the left end of this section starting with the win probability from its right endpoint.
That we are asking for is an arbitrary interval \ (Vall \) .

Consider a range of \ (Val \) how to transfer it comes from two sub-intervals.

For the first \ (Vall \)
must have a \ (S1.ValL \ Times S2.ValL \) , represents the \ (Sl \) the left departure and arrival points \ (S2 \) left point, then \ (R + 1 \) , but will obviously missing in \ (, S2 \) S1 period from repeated cross jump.
We enumerate at times it might be calculated lateral hops
\ [\ sum_ {i = 0
} ^ {\ infty} S1.ValR ^ i \ times (1-S2.ValL) ^ i \] simplifies to \ [\ frac {1} {1-S1.ValR
\ times (1-S2.ValL)} \] i.e. \ [ValL = \ frac {S1.ValL \ times S2.ValL} {1-S1.ValR \ times (1- S2.ValL)} \]


Similarly, for \ (ValR \) , there is a case of cross jump, but left the number of horizontal jump right there is a gap.
\ [(1-S2.ValR) \
times S2.ValL \ times \ sum_ {i = 0} ^ {\ infty} S1.ValR ^ {i + 1} \ times (1-S2.ValL) ^ i \] Simplification is \ [\ frac {(1-
S2.ValR) \ times S2.ValL \ times S1.ValR} {1-S1.ValR \ times (1-S2.ValL)} \] Meanwhile, \ (ValR \ ) also without cross jump, i.e. \ (S2.ValR \) .
comprehensive look
\ [ValR = S2.ValR + \ frac {(1-S2.ValR) \ times S2.ValL \ times S1.ValR} {1- S1.ValR \ times (1-S2.ValL) } \]

For ValL and ValR, you can use the tree line maintenance.

Code

Did not play overloading, violent merger

#include<cstdio>
#include<algorithm>
using namespace std;
#define fi first
#define se second
const double ONE=1.0;
const int MAXN=100005;
const int INF=0X3F3F3F3F;
int N,Q;
double P[MAXN];
struct Node{
    int l,r;pair<double,double>val;
}s[MAXN*8];
void Push_Up(int rt){
    pair<double,double>ret1=s[rt*2].val,ret2=s[rt*2+1].val;
    s[rt].val.fi=ret1.fi*ret2.fi/(1-ret1.se*(1-ret2.fi));
    s[rt].val.se=ret2.se+(1-ret2.se)*ret2.fi*ret1.se/(1-ret1.se*(1-ret2.fi));
}
void Build(int rt,int l,int r){
    s[rt].l=l;s[rt].r=r;
    s[rt].val.fi=s[rt].val.se=-INF;
    if(l==r){
        s[rt].val.fi=P[l];
        s[rt].val.se=P[l];
        return ;
    }
    int mid=(l+r)/2;
    Build(rt*2,l,mid);
    Build(rt*2+1,mid+1,r);
    Push_Up(rt);
}
void Insert(int rt,int p,double val){
    if(s[rt].l>p||s[rt].r<p)return ;
    if(s[rt].l==s[rt].r){s[rt].val.fi=s[rt].val.se=val;return ;}
    Insert(rt*2,p,val);Insert(rt*2+1,p,val);Push_Up(rt);
}
pair<double,double>Query(int rt,int l,int r){
    pair<double,double>ret;ret.fi=ret.se=-INF;
    if(s[rt].l>r||s[rt].r<l)return ret;
    if(s[rt].l>=l&&s[rt].r<=r)return s[rt].val;
    pair<double,double>ret1,ret2;
    ret1=Query(rt*2,l,r);
    ret2=Query(rt*2+1,l,r);
    if(ret1.fi==-INF&&ret2.fi==-INF)return ret;
    if(ret1.fi==-INF)ret=ret2;
    else if(ret2.fi==-INF)ret=ret1;
    else{
        ret.fi=ret1.fi*ret2.fi/(1-ret1.se*(1-ret2.fi));
        ret.se=ret2.se+(1-ret2.se)*ret2.fi*ret1.se/(1-ret1.se*(1-ret2.fi));
    }
    return ret;
}
int main(){
    scanf("%d%d",&N,&Q);
    for(int i=1,A,B;i<=N;i++){
        scanf("%d%d",&A,&B);
        P[i]=ONE*A/B;
    }
    Build(1,1,N);
    for(int i=1,k,x,y,z;i<=Q;i++){
        scanf("%d%d%d",&k,&x,&y);
        if(k==1){
            scanf("%d",&z);
            Insert(1,x,ONE*y/z);
        }
        if(k==2)printf("%.10f\n",Query(1,x,y).fi);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/ftotl/p/11771284.html