• Codeforces712E


    传送门 here

    题意:

    有n个赌场,第i个赌场的胜率为$ P_i$,在第i个赌场若取胜则到达第$ i+1$个赌场,反之到达第$ i-1$个赌场

    定义统治赌场$ L...R$为从赌场$ L$开始,从赌场$ R+1$结束且期间没有到达过$ L$前面的赌场(没有在赌场$ L$输过)

    有$ q$次操作,修改一个赌场的胜率或者询问统治赌场$ L...R$的概率

    这题真的很妙啊...

    我们定义$ f(i)$为从i走到目标地点的概率

    显然当询问$ L...R$时有$ f(L-1)=0,f(R+1)=1$

    根据题意有$ f(i)=P_if(i+1)+(1-P_i)f(i-1)$

    移项得$ f(i)-f(i-1)=P_if(i+1)+(1-1-P_i)f(i-1)=P_i(f(i+1)-f(i-1))$

    定义$ g(i)=f(i)-f(i-1)$

    则有$ g(i)=P_i(f(i+1)-f(i-1))$

    容易发现$ g(L)=f(L)$也就是所要求的答案

    计算$ g(i+1)+g(i)=f(i+1)-f(i)+f(i)-f(i-1)=f(i+1)-f(i-1)=frac{1}{P_i}g(i)$

    因而有$ g(i+1)=frac{1-P_i}{P_i}g(i)$

    根据g的定义有$ sumlimits_{i=L}^Rg(i)=f(R+1)-f(L-1)=1$

    我们又知道$ g(i+1)$和$ g(i)$的比值关系,设为$ t_i$

    则有$ g(L)*(1+t_L+t_Lt_{L+1}+...+t_{L}*...*t_{R})=1$

    就可以用线段树维护t的信息计算结果了

    由于只需要四位精度,因此当括号内的数超过$ 10000$即可跳出避免爆double

    my code:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define rt register int
    #define ll long long
    #define r read()
    using namespace std;
    ll read()
    {
        ll x = 0; int zf = 1; char ch;
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    int i,j,k,m,n,x,y,z,cnt,all,num;
    double p[100010],val[100010],qz[100010];
    struct segment_tree{
        int L,R;double val,ji;
    }a[400010];
    void build(const int x,const int L,const int R)
    {
        a[x].L=L;a[x].R=R;
        if(L==R)
        {
            a[x].val=a[x].ji=val[L];
            return;
        }
        const int mid=L+R>>1;
        build(x<<1,L,mid);build(x<<1|1,mid+1,R);
        a[x].val=a[x<<1].val+a[x<<1|1].val*a[x<<1].ji;
        a[x].ji=a[x<<1].ji*a[x<<1|1].ji;
    }
    void change(const int x,const int L,const double val)
    {
        if(a[x].L==a[x].R)
        {
            a[x].val=a[x].ji=val;
            return;
        }
        L<=a[x].L+a[x].R>>1?change(x<<1,L,val):change(x<<1|1,L,val);
        a[x].val=a[x<<1].val+a[x<<1|1].val*a[x<<1].ji;
        a[x].ji=a[x<<1].ji*a[x<<1|1].ji;
    }
    double ansa,ansb;
    void query(const int x,const int L,const int R)
    {
        if(ansa>10000)return;
        if(a[x].L>R||a[x].R<L)return;
        if(a[x].L>=L&&a[x].R<=R)
        {
            ansa+=a[x].val*ansb;
            ansb*=a[x].ji;
            return;
        }
        query(x<<1,L,R);query(x<<1|1,L,R);
    }
    int main()
    {
        n=r;m=r;
        for(rt i=1;i<=n;i++)
        {
            x=r;y=r;
            p[i]=(double)x/(double)y;
            val[i]=(1-p[i])/p[i];
        }
        build(1,1,n);
        while(m--)
        {
            int opt=r;
            if(opt==2)
            {
                int L=r,R=r;ansa=0;ansb=1;query(1,L,R);
                printf("%.6f
    ",1/(ansa+1));
            }
            else
            {
                int L=r;x=r;y=r;
                double t=(double)x/(double)y;
                change(1,L,(1-t)/t);
                p[L]=t;
            }
        }
        return 0;
    }
  • 相关阅读:
    RxJava Android(RxAndroid) 开发全家桶
    Android Retrofit RxJava实现缓存
    Android Touch事件传递机制详解 下
    Android Touch事件传递机制详解 上
    Android Framework 记录之二
    XMind 8 Update 7 Pro 激活码
    leetcode 2-> Add Two Numbers
    leetcode 1 -> Two Sum
    leetcode 3-> Longest Substring Without Repeating Characters
    Python enumerate() 函数
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/9030968.html
Copyright © 2020-2023  润新知