cf 712E Memory and Casinos

题意:有一行$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 << 31) - 1);
 39 const double double_inf = 1e30;
 40 const double eps = 1e-14;
 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 0;
 63     int tem = (int)((double)rand() / RAND_MAX * x) % x;
 64     return o ? tem + 1 : tem;
 65 }
 66 ll ll_rand(ll x, int o) {
 67     if (!x) return 0;
 68     ll tem = (ll)((double)rand() / RAND_MAX * x) % x;
 69     return o ? tem + 1 : tem;
 70 }
 71
 72 void data_gen() {
 73     srand(time(0));
 74     freopen("in.txt", "w", stdout);
 75     int kases = 1;
 76     //printf("%d\n", kases);
 77     while (kases--) {
 78         ll sz = 1000;
 79         printf("%d %d\n", sz, sz);
 80         FOR(i, 1, sz) {
 81             int x = Rand(1e2, 1);
 82             int y = Rand(1e9, 1);
 83             if (x > y) swap(x, y);
 84             printf("%d %d\n", x, y);
 85         }
 86         FOR(i, 1, sz) {
 87             int o = Rand(2, 0);
 88             if (o) {
 89                 printf("1 ");
 90                 int pos = Rand(1000, 1);
 91                 int x = Rand(1e9, 1), y = Rand(1e9, 1);
 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(1000, 1), y = Rand(1e3, 1);
 97                 if (x > y) swap(x, y);
 98                 printf("%d %d\n", x, y);
 99             }
100         }
101     }
102 }
103
104 const int maxn = 1e5 + 10;
105 struct Seg {
106     double l1, l2, r1, r2;
107 }seg[maxn << 2];
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 / (1 - seg[lson].r1 * seg[rson].l1);
113     seg[u].l1 = seg[lson].l1 + seg[lson].l2 * seg[lson].r2 * seg[rson].l1 / (1 - seg[lson].r1 * seg[rson].l1);
114     seg[u].r1 = seg[rson].r1 + seg[rson].r2 * seg[rson].l2 * seg[lson].r1 / (1 - seg[lson].r1 * seg[rson].l1);
115     seg[u].r2 = seg[lson].r2 * seg[rson].r2 / (1 - 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) >> 1;
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 / (1. - 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) >> 1;
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 / (1. - 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) >> 1;
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 / (1. - 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) >> 1;
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 / (1. - R1 * L1);
166 }
167
168 void build(int u, int l, int r) {
169     if (r - l < 2) {
170         double p = (double)a[l].first / a[l].nd;
171         seg[u].l1 = 1 - p;
172         seg[u].l2 = p;
173         seg[u].r1 = p;
174         seg[u].r2 = 1 - p;
175         return;
176     }
177     int mid = (l + r) >> 1;
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 = 1 - p;
186         seg[u].l2 = p;
187         seg[u].r1 = p;
188         seg[u].r2 = 1 - p;
189         return;
190     }
191     int mid = (l + r) >> 1;
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(1, 1, n + 1, x, y + 1);
199 }
200
201 void __set(int x, int y, int z) {
202     update(1, 1, n + 1, x, x + 1, y, z);
203 }
204
205 int main() {
206     //data_gen(); return 0;
207     //C(); return 0;
208     int debug = 0;
209     if (debug) freopen("in.txt", "r", stdin);
210     //freopen("out.txt", "w", stdout);
211     while (~scanf("%d%d", &n, &q)) {
212         FOR(i, 1, n) scanf("%d%d", &a[i].first, &a[i].nd);
213         build(1, 1, n + 1);
214         FOR(i, 1, q) {
215             int op, x, y, z;
216             scanf("%d%d%d", &op, &x, &y);
217             if (op == 1) {
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 0;
227 }

时间: 2024-11-10 14:27:17

cf 712E Memory and Casinos的相关文章

cpdeforces 712 E. Memory and Casinos 概率论 + 线段树

给出一个数组p,长度为n,1  <= n  <= 10^5 表示有n个格子,在第i个格子,你有p[i]的概率会到i + 1,有1 - p[i]的概率会到i - 1 如果在区间[l,r]上玩游戏,我们规定你起点在l,然后你开始走, 如果你到了l - 1,那么你失败了,游戏结束 如果你到了r + 1,那么你成功了,游戏结束 现在有q个操作,1 <= q <= 10^5 1 i a b   修改p[i] = (double)a / b 2 l r      询问在[l,r]上玩游戏,成功

CF712E Memory and Casinos

Link 设\(f(l,r)\)为从\(l\)走到\(r+1\)并且在\(l,r\)没有输过的概率,\(g(l,r)\)为从\(r\)走到\(l-1\)并且在\(l,r\)没有赢过的概率. 那么这题看上去就很线段树了对吧. 首先很显然\(f(i,i)=p_i,g(i,i)=1-p_i\). 然后考虑合并\([l,mid],(mid,r]\)的答案. 枚举跨过\((mid,mid+1)\)这一分界线然后又走回来的次数,可以得到\(f(l,r)=f(l,mid)f(mid+1,r)\sum\limi

数码相机SD卡文件格式化了怎么恢复

SD卡是一种广泛运用于数码相机.手机.多媒体播放器等便携设备上的存储记忆卡.作为使用最广泛的存储载体,SD卡因为拥有高记忆容量.快速数据传输率.极大的移动灵活性以及很好的安全性,同时性价比比较高,被大多数数码相机采用.在数据安全性方面,SD卡文件丢失是一个不容忽视的问题,格式化就是最常见的一种.那么,数码相机SD卡文件格式化了怎么恢复呢?SD卡格式化之后的恢复方法一般有三种. 第一种是从备份中恢复.一定要备份,我相信这是大多数有过数据丢失经历的小伙伴们都深有体会.当你出去旅行拍完照片,回来之后,

华为交换机硬件信息查看命令

查看主控板.业务板信息 display version [HUAWEI]dis verHuawei Versatile Routing Platform SoftwareVRP (R) software, Version 5.130 (S7700 V200R003C00SPC500)Copyright (C) 2000-2013 HUAWEI TECH CO., LTDQuidway S7703 Terabit Routing Switch uptime is 19 weeks, 5 days,

小猪猪教你如何找回相机存储卡内的丢失数据

大家一般所说的相机卡, 不管是CF卡, SD卡, XD卡等, 其实都属于数据存储卡.因为一般的数码相机的默认内置空间是1-2G, 是没有办法满足存储大量数码照片的, 因此大多数相机都有卡槽可供增加额外的存储卡.因为误删, 格式化, 存储卡的读取故障,相机存储卡的数据属于最容易丢失的类型之一. 有什么办法可以找回相机存储卡内的丢失数据吗? 因为有一些相机有删除全部照片的功能, 有的时候将相机连在电脑上, 因为一些存储卡错误, 电脑系统 会提醒你格式化存储卡, 有的用户不小心就将存储卡给格式化了,结

CF 187C Weak Memory 优先队列 难度:2

http://codeforces.com/problemset/problem/187/C 这道题可以用二分+dfs检测,或者优先队列解 此处用了优先队列解法 从起点出发,维护一个优先队列,内容是pair<当前所需最小容量,节点序号>,则每一次取出的都一定是最小容量,也就是说结果必然大于等于这个容量 #include <cstdio> #include <queue> #include <cstring> using namespace std; type

cf 20C Dijkstra?

带队列  dijkstra 1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <vector> 5 #include<memory.h> 6 #include<algorithm>//reverse 7 using namespace std; 8 #define maxn 100002 9 #define INF 65 10 struct

[2016-02-05][CF][380A][Sereja and Prefixes]

[2016-02-05][CF][380A][Sereja and Prefixes] CodeForces - 380A Sereja and Prefixes Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit Status Description Sereja loves number sequences very much. That's why he decided to mak

spark MLlib 概念 4: 协同过滤(CF)

1. 定义 协同过滤(Collaborative Filtering)有狭义和广义两种意义: 广义协同过滤:对来源不同的数据,根据他们的共同点做过滤处理. Collaborative filtering (CF) is a technique used by some recommender systems.[1] Collaborative filtering has two senses, a narrow one and a more general one.[2] In general,