CF712E Memory and Casinos

题目描述:

luogu

CF

题解:

一眼线段树维护区间某值,然后就不会了……

肝到$O(nq)$就弃疗了,题解的方法比较奇妙。

我的$O(nq)$做法是$$f_i=k_{i-1}*f_{i-1}+(1-k_{i+1})*f_{i+1}$$,最后取$f_r$,是一个概率方程;

而题解是这样的:$$f_i=(1-k_{i})*f_{i-1}+k_{i}*f_{i+1}$$,最后取$f_l$,是一个期望方程……

这个期望方程可以变成:$$f_i-f_{i-1}=k_i*(f_{i+1}-f_{i-1})$$

然后设$g_i=f_i-f_{i-1}$,则上式可变成:$$g_i=k_i*(g_{i+1}+g_i)$$

然后:$$ frac {1-k_i}{k_i} * g_i = g_{i+1}$$

设$t_i = frac{1-k_i}{k_i}$,$t_0 = 1$;

我们知道$f_{l-1}=0$(感性理解一下),$f_{r}=1$,所以说$g_l * sum_{ i = l}^{ r } prod_{j = 0}^{ i - 1 }t_j = 1$

 展开写出来大概是这样的:$$g_l * (1+t_l+t_l*t_{l+1}+……+t_l*t_{l+1}*……*t_{r-1}) = 1$$

然后线段树维护两个值:一个是$t_i*t_{i+1}*……$,另一个是$t_l+t_l*t_{l+1}+……$。

然后转移就好了。时间复杂度$O(qlogn)$。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100500;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,m;
double k[N];
struct Pair
{
    double a,b;
    Pair(){}
    Pair(double a,double b):a(a),b(b){}
    Pair operator + (const Pair&x)const{return Pair(a+x.a*b,b*x.b);}
};

struct segtree
{
    Pair p[N<<2];
    void update(int u)
    {
        p[u] = p[u<<1]+p[u<<1|1];
    }
    void build(int l,int r,int u)
    {
        if(l==r)
        {
            p[u] = Pair(k[l],k[l]);
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,u<<1);
        build(mid+1,r,u<<1|1);
        update(u);
    }
    void insert(int l,int r,int u,int qx,double d)
    {
        if(l==r){p[u]=Pair(k[l],k[l]);return ;}
        int mid = (l+r)>>1;
        if(qx<=mid)insert(l,mid,u<<1,qx,d);
        else insert(mid+1,r,u<<1|1,qx,d);
        update(u);
    }
    Pair query(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return p[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,u<<1,ql,qr);
        else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
        else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr);
    }
}tr;
int main()
{
    read(n),read(m);
    ll X,Y;
    for(int i=1;i<=n;i++)
    {
        read(X),read(Y);
        k[i] = (double)(Y-X)/(X);
    }
    tr.build(1,n,1);
    for(int op,d,l,r,i=1;i<=m;i++)
    {
        read(op);
        if(op==1)
        {
            read(d),read(X),read(Y);
            k[d] = (double)(Y-X)/(X);
            tr.insert(1,n,1,d,k[d]);
        }else
        {
            read(l),read(r);
            Pair ans = tr.query(1,n,1,l,r);
            printf("%.10lf
",1.0/(ans.a+1.0));
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10973757.html