Codeforces Round #370 (Div. 2) E. Memory and Casinos 线段树

题意

在第i个位置,你有pi的概率走到i+1,有(1-pi)的概率走到i-1

单点修改概率

区间查询从L开始,从R离开的概率是多少

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
typedef pair<double,double> SgTreeDataType;
struct treenode
{
  int L , R  ;
  SgTreeDataType A;
  void updata(SgTreeDataType v)
  {
      A=v;
  }
};
pair<double,double>tmp=make_pair(1.0,0);
treenode tree[maxn*4];

inline void push_up(int o)
{
    tree[o].A.first = tree[o*2].A.first*tree[o*2+1].A.first;
    tree[o].A.second = tree[o*2].A.second + tree[o*2+1].A.second * tree[o*2].A.first;
}

inline void build_tree(int L , int R , int o)
{
    tree[o].L = L , tree[o].R = R;
    if (R > L)
    {
        int mid = (L+R) >> 1;
        build_tree(L,mid,o*2);
        build_tree(mid+1,R,o*2+1);
    }
}

inline void update(int QL,int QR,SgTreeDataType v,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) tree[o].updata(v);
    else
    {
        int mid = (L+R)>>1;
        if (QL <= mid) update(QL,QR,v,o*2);
        if (QR >  mid) update(QL,QR,v,o*2+1);
        push_up(o);
    }
}

inline SgTreeDataType query(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) return tree[o].A;
    else
    {
        int mid = (L+R)>>1;
        SgTreeDataType AA=tmp,BB=tmp,CC;
        if (QL <= mid) AA = query(QL,QR,2*o);
        if (QR > mid) BB = query(QL,QR,2*o+1);
        push_up(o);
        CC.first=AA.first*BB.first;
        CC.second=AA.second+BB.second*AA.first;
        return CC;
    }
}



int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    build_tree(1,n,1);
    for(int i=1;i<=n;i++)
    {
        double a,b;
        cin>>a>>b;
        double p = a/b;
        update(i,i,make_pair((1.0-p)/p,(1.0-p)/p),1);
    }
    for(int i=1;i<=q;i++)
    {
        int op,a,b,c;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&a,&b,&c);
            double p = 1.0*b/(1.0*c);
            pair<double,double>D=make_pair((1-p)/p,(1-p)/p);
            update(a,a,D,1);
        }
        else
        {
            scanf("%d%d",&a,&b);
            double p = query(a,b,1).second;
            if(p<1e20)printf("%.12f\n",1.0/(1.0+p));
            else printf("0.000000000000\n");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值