首页 > 其他 > 详细

CF712E Memory and Casinos

时间:2020-01-26 20:28:21      阅读:76      评论:0      收藏:0      [点我收藏+]

Link
\(f(l,r)\)为从\(l\)走到\(r+1\)并且在\(l,r\)没有输过的概率,\(g(l,r)\)为从\(r\)走到\(l-1\)并且在\(l,r\)没有赢过的概率。
那么这题看上去就很线段树了对吧。
首先很显然\(f(i,i)=p_i,g(i,i)=1-p_i\)
然后考虑合并\([l,mid],(mid,r]\)的答案。
枚举跨过\((mid,mid+1)\)这一分界线然后又走回来的次数,可以得到\(f(l,r)=f(l,mid)f(mid+1,r)\sum\limits_i((1-f(mid+1,r))(1-g(l,mid)))^i\)
显然这个幂级数收敛,所以\(f(l,r)=\frac{f(l,mid)f(mid+1,r)}{1-(1-f(mid+1,r))(1-g(l,mid))}\)
同理可得\(g(l,r)=\frac{g(l,mid)g(mid+1,r)}{1-(1-f(mid+1,r))(1-g(l,mid))}\)
然后线段树随便维护一下就完事了。

#include<cstdio>
#include<cctype>
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}using IO::read;
using db=double;
const int N=100007;
struct node{db f,g;}t[N<<2];db p[N];
node operator+(const node&a,const node&b){return {a.f*b.f/(1-(1-b.f)*(1-a.g)),a.g*b.g/(1-(1-b.f)*(1-a.g))};}
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
void pushup(int p){t[p]=t[ls]+t[rs];}
void modify(int p,db v){t[p]={v,1-v};}
void build(int p,int l,int r)
{
    if(l==r) return modify(p,1.0*read()/read());
    build(ls,l,mid),build(rs,mid+1,r),pushup(p);
}
void update(int p,int l,int r,int x)
{
    if(l==r) return modify(p,1.0*read()/read());
    (x<=mid? update(ls,l,mid,x):update(rs,mid+1,r,x)),pushup(p);
}
node query(int p,int l,int r,int L,int R)
{
    if(L<=l&&r<=R) return t[p];
    if(r<L||R<l) return {1,1};
    return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R);
}
int main()
{
    int n=read(),q=read();
    build(1,1,n);
    for(int x;q;--q) read()==1? update(1,1,n,read()):(x=read(),printf("%.6lf\n",query(1,1,n,x,read()).f),void());
}

CF712E Memory and Casinos

原文:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12234697.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!