题意:有一行$n(n \leq 100000)$个方格,从左往右第$i$个方格的值为$p_i(p_i = \frac{a}{b}, 1 \leq a < b \leq 1e9)$,有两种操作,一种是将某个方格的值更新为另一个分数表示的有理数,另一种操作是寻味区间$[l, r](l \leq r)$的权值$w(l, r)$;$w(l, r)$如下定义:

方格在位置$i$有$p_i$的概率向右移动一格,有$1-p_i$的概率向左移动一格。$w(l, r)$表示方格初始位置在$l$并且以在位置$r$向右移动(下一个位置为$r+1$)为终结,移动过程始终不超出区间范围的概率值。

分析:对于任一区间$[l, r]$,设$f(i)$表示目前在位置$i$,在移动合法的情况下到达终结状态的概率值。那么显然有$f(i) = p_if(i + 1) + (1 - p_i)f(i - 1)$,注意边界情况是$f(l - 1) = 0$, 且$f(r + 1) = 1$,我们设$w(l, r) = f(l) = \Delta$,那么可以得到递推关系$f(r + 1) = 1 = g(r + 1) + f(r - 1)$,其中$g(r + 1) = \frac{\prod_{i \leq r - 1}(1 - p_i)}{\prod_{i \leq r}p_i} $,理论上我们可以用$g(i)$前缀和得到任意区间的和,用线段树分别维护奇数位置和偶数位置即可。然而,由于$g(i)$可能会非常大,以至于double存储失效,因此此方法并不可行。

用分类统计的方法来解,考虑小规模问题与大规模问题之间的联系,$[l, r]$中间一任意位置为$m$,讨论方格穿过$m$的次数(等比求和),于是可以得到具有局部可累加性质的递推关系。用线段上进行点维护和区间查询即可。单次询问复杂度$O(log(n))$。

code:

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <queue>
  6. #include <map>
  7. #include <set>
  8. #include <stack>
  9. #include <ctime>
  10. #include <cmath>
  11. #include <iostream>
  12. #include <assert.h>
  13. #pragma comment(linker, "/STACK:102400000,102400000")
  14. #define max(a, b) ((a) > (b) ? (a) : (b))
  15. #define min(a, b) ((a) < (b) ? (a) : (b))
  16. #define mp std :: make_pair
  17. #define st first
  18. #define nd second
  19. #define keyn (root->ch[1]->ch[0])
  20. #define lson (u << 1)
  21. #define rson (u << 1 | 1)
  22. #define pii std :: pair<int, int>
  23. #define pll pair<ll, ll>
  24. #define pb push_back
  25. #define type(x) __typeof(x.begin())
  26. #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
  27. #define FOR(i, s, t) for(int i = (s); i <= (t); i++)
  28. #define ROF(i, t, s) for(int i = (t); i >= (s); i--)
  29. #define dbg(x) std::cout << x << std::endl
  30. #define dbg2(x, y) std::cout << x << " " << y << std::endl
  31. #define clr(x, i) memset(x, (i), sizeof(x))
  32. #define maximize(x, y) x = max((x), (y))
  33. #define minimize(x, y) x = min((x), (y))
  34. using namespace std;
  35. typedef long long ll;
  36. const int int_inf = 0x3f3f3f3f;
  37. const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
  38. const int INT_INF = (int)((1ll << ) - );
  39. const double double_inf = 1e30;
  40. const double eps = 1e-;
  41. typedef unsigned long long ul;
  42. typedef unsigned int ui;
  43. inline int readint() {
  44. int x;
  45. scanf("%d", &x);
  46. return x;
  47. }
  48. inline int readstr(char *s) {
  49. scanf("%s", s);
  50. return strlen(s);
  51. }
  52.  
  53. class cmpt {
  54. public:
  55. bool operator () (const int &x, const int &y) const {
  56. return x > y;
  57. }
  58. };
  59.  
  60. int Rand(int x, int o) {
  61. //if o set, return [1, x], else return [0, x - 1]
  62. if (!x) return ;
  63. int tem = (int)((double)rand() / RAND_MAX * x) % x;
  64. return o ? tem + : tem;
  65. }
  66. ll ll_rand(ll x, int o) {
  67. if (!x) return ;
  68. ll tem = (ll)((double)rand() / RAND_MAX * x) % x;
  69. return o ? tem + : tem;
  70. }
  71.  
  72. void data_gen() {
  73. srand(time());
  74. freopen("in.txt", "w", stdout);
  75. int kases = ;
  76. //printf("%d\n", kases);
  77. while (kases--) {
  78. ll sz = ;
  79. printf("%d %d\n", sz, sz);
  80. FOR(i, , sz) {
  81. int x = Rand(1e2, );
  82. int y = Rand(1e9, );
  83. if (x > y) swap(x, y);
  84. printf("%d %d\n", x, y);
  85. }
  86. FOR(i, , sz) {
  87. int o = Rand(, );
  88. if (o) {
  89. printf("1 ");
  90. int pos = Rand(, );
  91. int x = Rand(1e9, ), y = Rand(1e9, );
  92. if (x > y) swap(x, y);
  93. printf("%d %d %d\n", pos, x, y);
  94. } else {
  95. printf("2 ");
  96. int x = Rand(, ), y = Rand(1e3, );
  97. if (x > y) swap(x, y);
  98. printf("%d %d\n", x, y);
  99. }
  100. }
  101. }
  102. }
  103.  
  104. const int maxn = 1e5 + ;
  105. struct Seg {
  106. double l1, l2, r1, r2;
  107. }seg[maxn << ];
  108. int n, q;
  109. pii a[maxn];
  110.  
  111. void push_up(int u) {
  112. seg[u].l2 = seg[lson].l2 * seg[rson].l2 / ( - seg[lson].r1 * seg[rson].l1);
  113. seg[u].l1 = seg[lson].l1 + seg[lson].l2 * seg[lson].r2 * seg[rson].l1 / ( - seg[lson].r1 * seg[rson].l1);
  114. seg[u].r1 = seg[rson].r1 + seg[rson].r2 * seg[rson].l2 * seg[lson].r1 / ( - seg[lson].r1 * seg[rson].l1);
  115. seg[u].r2 = seg[lson].r2 * seg[rson].r2 / ( - seg[lson].r1 * seg[rson].l1);
  116. }
  117.  
  118. double query1(int u, int l, int r, int L, int R);
  119. double query3(int u, int l, int r, int L, int R);
  120. double query4(int u, int l, int r, int L, int R);
  121.  
  122. double query(int u, int l, int r, int L, int R) {
  123. if (l == L && R == r) return seg[u].l2;
  124. int mid = (l + r) >> ;
  125. if (R <= mid) return query(lson, l, mid, L, R);
  126. else if (L >= mid) return query(rson, mid, r, L, R);
  127. double lhs = query(lson, l, mid, L, mid), rhs = query(rson, mid, r, mid, R);
  128. double L1 = query1(rson, mid, r, mid, R), R1 = query3(lson, l, mid, L, mid);
  129. return lhs * rhs / (. - L1 * R1);
  130. }
  131.  
  132. double query3(int u, int l, int r, int L, int R) {
  133. if (l == L && r == R) return seg[u].r1;
  134. int mid = (l + r) >> ;
  135. if (R <= mid) return query3(lson, l, mid, L, R);
  136. else if (L >= mid) return query3(rson, mid, r, L, R);
  137. double tem = query3(rson, mid, r, mid, R);
  138. double R2 = query4(rson, mid, r, mid, R);
  139. double R1 = query3(lson, l, mid, L, mid);
  140. double L2 = query(rson, mid, r, mid, R);
  141. double L1 = query1(rson, mid, r, mid, R);
  142. return tem + R2 * R1 * L2 / (. - L1 * R1);
  143. }
  144.  
  145. double query4(int u, int l, int r, int L, int R) {
  146. if (l == L && r == R) return seg[u].r2;
  147. int mid = (l + r) >> ;
  148. if (R <= mid) return query4(lson, l, mid, L, R);
  149. else if (L >= mid) return query4(rson, mid, r, L, R);
  150. double lhs = query4(lson, l, mid, L, mid) * query4(rson, mid, r, mid, R);
  151. double rhs = query3(lson, l, mid, L, mid) * query3(rson, mid, r, mid, R);
  152. return lhs / (. - rhs);
  153. }
  154.  
  155. double query1(int u, int l, int r, int L, int R) {
  156. if (l == L && R == r) return seg[u].l1;
  157. int mid = (l + r) >> ;
  158. if (R <= mid) return query1(lson, l, mid, L, R);
  159. else if (L >= mid) return query1(rson, mid, r, L, R);
  160. double tem = query1(lson, l, mid, L, mid);
  161. double L1 = query1(rson, mid, r, mid, R);
  162. double L2 = query(lson, l, mid, L, mid);
  163. double R2 = query4(lson, l, mid, L, mid);
  164. double R1 = query3(lson, l, mid, L, mid);
  165. return tem + L2 * L1 * R2 / (. - R1 * L1);
  166. }
  167.  
  168. void build(int u, int l, int r) {
  169. if (r - l < ) {
  170. double p = (double)a[l].first / a[l].nd;
  171. seg[u].l1 = - p;
  172. seg[u].l2 = p;
  173. seg[u].r1 = p;
  174. seg[u].r2 = - p;
  175. return;
  176. }
  177. int mid = (l + r) >> ;
  178. build(lson, l, mid), build(rson, mid, r);
  179. push_up(u);
  180. }
  181.  
  182. void update(int u, int l, int r, int L, int R, int lhs, int rhs) {
  183. if (l == L && r == R) {
  184. double p = (double)lhs / rhs;
  185. seg[u].l1 = - p;
  186. seg[u].l2 = p;
  187. seg[u].r1 = p;
  188. seg[u].r2 = - p;
  189. return;
  190. }
  191. int mid = (l + r) >> ;
  192. if (R <= mid) update(lson, l, mid, L, R, lhs, rhs);
  193. else update(rson, mid, r, L, R, lhs, rhs);
  194. push_up(u);
  195. }
  196.  
  197. double __get(int x, int y) {
  198. return query(, , n + , x, y + );
  199. }
  200.  
  201. void __set(int x, int y, int z) {
  202. update(, , n + , x, x + , y, z);
  203. }
  204.  
  205. int main() {
  206. //data_gen(); return 0;
  207. //C(); return 0;
  208. int debug = ;
  209. if (debug) freopen("in.txt", "r", stdin);
  210. //freopen("out.txt", "w", stdout);
  211. while (~scanf("%d%d", &n, &q)) {
  212. FOR(i, , n) scanf("%d%d", &a[i].first, &a[i].nd);
  213. build(, , n + );
  214. FOR(i, , q) {
  215. int op, x, y, z;
  216. scanf("%d%d%d", &op, &x, &y);
  217. if (op == ) {
  218. z = readint();
  219. __set(x, y, z);
  220. } else {
  221. double ans = __get(x, y);
  222. printf("%.10f\n", ans);
  223. }
  224. }
  225. }
  226. return ;
  227. }

cf 712E Memory and Casinos的更多相关文章

  1. Codeforces 712E Memory and Casinos

    Description There are n casinos lined in a row. If Memory plays at casino \(i\), he has probability ...

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

    E. Memory and Casinos 题目连接: http://codeforces.com/contest/712/problem/E Description There are n casi ...

  3. Memory and Casinos CodeForces - 712E (概率,线段树)

    题目链接 题目大意:$n$个点, 每个点$i$有成功率$p_i$, 若成功走到$i+1$, 否则走到走到$i-1$, 多组询问, 求从$l$出发, 在$l$处不失败, 最后在$r$处胜利的概率 设$L ...

  4. Codeforces Round #370 (Div. 2) E. Memory and Casinos (数学&&概率&&线段树)

    题目链接: http://codeforces.com/contest/712/problem/E 题目大意: 一条直线上有n格,在第i格有pi的可能性向右走一格,1-pi的可能性向左走一格,有2中操 ...

  5. CF712E Memory and Casinos

    设\(f[i]\)为从\(i\)到\(r+1\)且不走出区间的概率 \(f[i]=p[i]f[i+1]+(1-p[i])f[i-1]\) \(f[i]-f[i-1]=p[i](f[i+1]-f[i-1 ...

  6. CF712E Memory and Casinos 期望概率

    题意:\(n\)个赌场,每个赌场有\(p_{i}\)的胜率,如果赢了就走到下一个赌场,输了就退回上一个赌场,规定\(1\)号赌场的上一个是\(0\)号赌场,\(n\)号赌场的下一个是\(n + 1\) ...

  7. 「CF712E」Memory and Casinos「线段树」「概率」

    题解 解法1:(官方做法) 一段区间的\(L\)定义为从最左边开始出发,最左不失败,一直到最右边胜利的概率,\(R\)定义为从最右边开始出发,最左不失败,又回到最右边胜利的概率 考虑一个区间\([l, ...

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

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

  9. simotion读写CF卡,保存/读取变量

    simotion读写CF卡功能 1 使用西门子的Simotion运动控制器时,有时需要用到 读/写 CF卡的功能.主要来自以下几个方面的需求. 1)用户数据量较大,可保持(retain)存储区的容量不 ...

随机推荐

  1. js按键监听

    //回车键监听 function keypressed(){ if(event.keyCode == 13) { doAction(); } } document.onkeydown = keypre ...

  2. JPA 2.1 Coverter 注解

    @Converter(autoApply = true) public class VehicleConverter implements AttributeConverter<Vehicle, ...

  3. log4net 按时间输出日志

    参考:(转)非常完善的Log4net详细说明 log4net 按天与按小时记日志的配置 Log4net 中输出日志到文件,文件名根据日期生成 log4net按日志级别(debug,info,warn, ...

  4. linux 安装配置Nginx

    简介: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国 ...

  5. Linuxb笔记

    3.登录mysql 开启MySQL服务后,使用MySQL命令可以登录.一般使用mysql -uroot -p即可.如果数据库不是本机,则需要加参数,常用参数如下:1,-h,指定ip地址,默认为loca ...

  6. 在html中引用分享的链接

    怎么说呢,其实我自己本身也不是很懂,这些到网上一搜也是有很多详解的,我就是水水的来~~ 附带:smarty 的 tpl 里面 要直接写 javascript 或 style 要用 literal 标签 ...

  7. HDU 4504 威威猫系列故事——篮球梦(dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=4504 题目大意: 中文都看得懂.不过我是看hint才正确理解什么意思的.开始的时候理解错了. 解题思路: 给定时 ...

  8. Dll的生成,转化为OMF格式的DLL

    extern "C" { __declspec(dllexport) int psq_add(int a, int b); } C:\Users\pansq>mkexp my ...

  9. Last time, I wrote a pager, but now it seems this no longer has use, so I want to paste it here.

    public class Pager<T> where T : new() { private IEnumerable<T> _all; private IEnumerable ...

  10. Java 线程的转换及状态

    线程的状态转换是线程控制的基础. 线程状态总的可分为五大状态:分别是生.死.可运行.运行.等待/阻塞.用一个图来描述如下: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnabl ...