• 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
    ", kases);
     77     while (kases--) {
     78         ll sz = 1000;
     79         printf("%d %d
    ", 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
    ", 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
    ", 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
    ", 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
    ", ans);
    223             }
    224         }
    225     }
    226     return 0;
    227 }
    View Code
  • 相关阅读:
    做了半年的答题小程序上线了
    党建答题助手小程序
    党建答题活动小程序
    微信答题活动小程序
    微信答题活动小程序
    如何搭建在线考试小程序
    如何搭建在线考试小程序
    基于云开发的在线答题小程序
    XLua访问C#中的List或者数组
    字符串、字节数组、流之间的相互转换以及文件MD5的计算
  • 原文地址:https://www.cnblogs.com/astoninfer/p/5869916.html
Copyright © 2020-2023  润新知