cf 712E Memory and Casinos

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
View Code

 

以上是关于cf 712E Memory and Casinos的主要内容,如果未能解决你的问题,请参考以下文章

CF712D Memory and Scores

CF 1348F Phoenix and Memory

CF 1348F Phoenix and Memory

CF游戏出现out of memory 怎么解决

cf老是出现out of memory

Cf老是掉线然后一串英文 out of memory