题解

解法1:(官方做法)

一段区间的\(L\)定义为从最左边开始出发,最左不失败,一直到最右边胜利的概率,\(R\)定义为从最右边开始出发,最左不失败,又回到最右边胜利的概率

考虑一个区间\([l, r]\)记为\(u\),左右儿子\([l, mid]\)和\([mid + 1, r]\)分别记为\(ls\)和\(rs\)

枚举一下\(mid\)和\(mid+1\)之间往返多少次

\[u.L = ls.L * rs.L * \sum_{i = 0}^{\infty} ls.R^i(1-rs.L)^i
\]

这玩意是无穷项等比数列求和:

\[u.L = \frac{ls.L * rs.L}{1 - ls.R * (1 - rs.L)}
\]

\(u.R\)分不过和过\(mid\)两种情况

\[u.R = rs.R + (1 - rs.R)*rs.L*ls.R\sum_{i = 0}^{\infty} (1 - rs.L)^i ls.R^i
\]

\[u.R = rs.R + (1 - rs.R)\frac{rs.L* ls.R}{1 - ls.R(1 - rs.L)}
\]

#include <algorithm>
#include <cstdio>
using namespace std; const int N = 1e5 + 10; struct node {
double L, R;
void rd() {
int x, y;
scanf("%d%d", &x, &y);
L = R = x * 1.0 / y;
}
} a[N << 2];
int n, q; node operator + (const node &ls, const node &rs) {
node ans;
ans.L = ls.L * rs.L / (1 - ls.R * (1 - rs.L));
ans.R = rs.R + (1 - rs.R) * rs.L * ls.R / (1 - ls.R * (1 - rs.L));
return ans;
} void build(int rt, int l, int r) {
if(l == r) {
a[rt].rd();
return ;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
a[rt] = a[rt << 1] + a[rt << 1 | 1];
} void modify(int rt, int l, int r, int x, double p) {
if(l == r) {
a[rt].L = a[rt].R = p;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) modify(rt << 1, l, mid, x, p);
else modify(rt << 1 | 1, mid + 1, r, x, p);
a[rt] = a[rt << 1] + a[rt << 1 | 1];
} node query(int rt, int l, int r, int ql, int qr) {
if(l == ql && r == qr) return a[rt];
int mid = (l + r) >> 1;
if(qr <= mid) return query(rt << 1, l, mid, ql, qr);
if(ql > mid) return query(rt << 1 | 1, mid + 1, r, ql, qr);
return query(rt << 1, l, mid, ql, mid) + query(rt << 1 | 1, mid + 1, r, mid + 1, qr);
} int main() {
scanf("%d%d", &n, &q);
build(1, 1, n);
int op, x, y, z;
while(q --) {
scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
scanf("%d", &z);
modify(1, 1, n, x, y * 1.0 / z);
}
if(op == 2) {
printf("%.10f\n", query(1, 1, n, x, y).L);
}
}
return 0;
}

解法2

\(dp[i]\)表示从\(i\)开始成功的概率

令\(dp[l - 1] = 0, dp[r + 1] = 1\),则\(dp[i] = dp[i - 1] * (1 - p[i]) + dp[i + 1] * p[i]\)

化简得:\(dp[i] - dp[i - 1] = p[i] * (dp[i + 1] - dp[i - 1])\)

令\(d[i] = dp[i] - dp[i - 1]\)

\(d[i] = p[i] * (d[i + 1] + d[i])\)

解得:\(d[i + 1] = \frac{1 - p[i]}{p[i]} d[i]\)

为了简便,令\(u[i] = \frac{1 - p[i]}{p[i]}\)

则递推式为\(d[i + 1] = u[i] * d[i]\)

考虑我们怎么求\(dp[l]\)(即\(d[l]\))

\(d[l] + d[l+1] + ... + d[r + 1] = dp[r + 1] - dp[l] = 1\)

所以\(d[l] (1 + u[l] + u[l] * u[l + 1] + ... + u[l] * u[l + 1] * u[l + 2] * .. * u[r]) = 1\)

\(d[l] = \frac{1}{1 + u[l] + u[l] * u[l + 1] + ... + u[l] * u[l + 1] * u[l + 2] * .. * u[r]}\)

线段树维护两个东西,一个是\(u\)的乘积,一个是所有前缀的乘积和,就做完了

代码就不写了

「CF712E」Memory and Casinos「线段树」「概率」的更多相关文章

  1. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

  2. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  3. 【tyvj】P2065 「Poetize10」封印一击(贪心+线段树/差分)

    http://new.tyvj.cn/p/2065 我就不说我很sb的用线段树来维护值...... 本机自测的时候想了老半天没想出怎么维护点在所有区间被多少区间包含的方法.最后一小时才想出来线段树(果 ...

  4. 【CF712E】Memory and Casinos(数学 期望 DP)

    题目链接 大意 给出一个序列,当你在某个点时,有一个向右走的概率\(P_i\)(向左为\(1-P_i\)), 给出\(M\)个操作,操作有两类: 1 X Y Z:把\(P_X\)的值修改为\(\fra ...

  5. 「10.29」数列(exgxd)·数对(线段树优化DP)·最小距离(最短路,树上直径思想)

    好久没碰到这么友好乱搞的题了.... A. 数列 考察的是exgcd的相关知识,最后的答案直接O(1)求即可 B. 数对 本来以为是原题,然后仔细看了看发现不是,发现不会只好乱搞骗分了 事实上直接按$ ...

  6. 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列

    hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...

  7. 「ZJOI2017」树状数组(二维线段树)

    「ZJOI2017」树状数组(二维线段树) 吉老师的题目真是难想... 代码中求的是 \(\sum_{i=l-1}^{r-1}a_i\),而实际求的是 \(\sum_{i=l}^{r}a_i\),所以 ...

  8. LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)

    题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...

  9. 【LibreOJ】#6396. 「THUPC2018」弗雷兹的玩具商店 / Toyshop 线段树+完全背包

    [题目]#6396. 「THUPC2018」弗雷兹的玩具商店 / Toyshop [题意]给定一个长度为n的物品序列,每个物品有价值.不超过m的重量.要求支持以下三种操作:1.物品价值区间加减,2.物 ...

随机推荐

  1. varnish HTTP头

    Cache-Control:指定了缓存如何处理内容.varnish关心max-age参数,并用它来计算对象的TTL.“Cache-Control:no-cache”是被忽略的.Age:varnish添 ...

  2. 为Vim 添加vimgdb支持

    为Vim 添加vimgdb支持 1.    下载最新的vim74的源码包 wget ftp://ftp.vim.org/pub/vim/unix/vim-7.4.tar.bz2 2.下载vimgdb- ...

  3. QT Creator 使用SVN的版本号做为编译的版本信息

    在使用qt Creator 开发中,如果想使用 svn 的源代码版本号来作为 build 的一个子版本号或者只是为了识别某个发布版本,与源代码的版本信息对应起来,可以方便调试对应的版本代码,我们可以通 ...

  4. 关于SpringMVC的几件小事

    一.SpringMVC表单标签He处理静态资源 1.Spring的表单标签 通过SpringMVC的表单标签可以实现将模型数据中的属性和HTML表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显. ...

  5. 1 java 笔记

    第一java的版本: J2ME主要用于移动设备和信息家电 J2SE整个Java技术的核心 J2EE java技术应用最广泛的部分,主要应用与企业的开发 第二:基于java语言的开源框架 struts ...

  6. 2.4 使用 xpath 对xml 进行解析

    public class Demo1 { /** * XPath提取XML文档数据 * xpath很强大 用来提取xml文档数据非常方便 * @throws Exception */ public s ...

  7. JPA自带findOne方法报错原因

    是由于jdk8的原因,有可能和spring boot的版本也关系, 两种方式可选 注册,返回类是Optional<Girl>, Optional是jdk8自带的 @GetMapping(v ...

  8. JAVA语言程序设计课后习题----第六单元解析(仅供参考)

    1 本题就是基本函数的用法 import java.util.Scanner; public class Poone { public static void main(String[] args) ...

  9. git回退到历史版本

    问题描述 在开发的过程中,想要修改一个参数的命名.然后修改各种地方,并且push上码云的远程仓库.然后突然发现还要改很多地方,突然后悔不想改动了.那该怎么办呢? 处理步骤 回退本地的git版本 将本地 ...

  10. linux usb驱动记录(一)

    一.linux 下的usb驱动框架 在linux系统中,usb驱动可以从两个角度去观察,一个是主机侧,一个是设备侧.linux usb 驱动的总体框架如下图所示:   从主机侧看usb驱动可分为四层: ...