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:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <ctime>
#include <cmath>
#include <iostream>
#include <assert.h>
#pragma comment(linker, "/STACK:102400000,102400000")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define mp std :: make_pair
#define st first
#define nd second
#define keyn (root->ch[1]->ch[0])
#define lson (u << 1)
#define rson (u << 1 | 1)
#define pii std :: pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define type(x) __typeof(x.begin())
#define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
#define FOR(i, s, t) for(int i = (s); i <= (t); i++)
#define ROF(i, t, s) for(int i = (t); i >= (s); i--)
#define dbg(x) std::cout << x << std::endl
#define dbg2(x, y) std::cout << x << " " << y << std::endl
#define clr(x, i) memset(x, (i), sizeof(x))
#define maximize(x, y) x = max((x), (y))
#define minimize(x, y) x = min((x), (y))
using namespace std;
typedef long long ll;
const int int_inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const int INT_INF = (int)((1ll << ) - );
const double double_inf = 1e30;
const double eps = 1e-;
typedef unsigned long long ul;
typedef unsigned int ui;
inline int readint() {
int x;
scanf("%d", &x);
return x;
}
inline int readstr(char *s) {
scanf("%s", s);
return strlen(s);
} class cmpt {
public:
bool operator () (const int &x, const int &y) const {
return x > y;
}
}; int Rand(int x, int o) {
//if o set, return [1, x], else return [0, x - 1]
if (!x) return ;
int tem = (int)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
}
ll ll_rand(ll x, int o) {
if (!x) return ;
ll tem = (ll)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
} void data_gen() {
srand(time());
freopen("in.txt", "w", stdout);
int kases = ;
//printf("%d\n", kases);
while (kases--) {
ll sz = ;
printf("%d %d\n", sz, sz);
FOR(i, , sz) {
int x = Rand(1e2, );
int y = Rand(1e9, );
if (x > y) swap(x, y);
printf("%d %d\n", x, y);
}
FOR(i, , sz) {
int o = Rand(, );
if (o) {
printf("1 ");
int pos = Rand(, );
int x = Rand(1e9, ), y = Rand(1e9, );
if (x > y) swap(x, y);
printf("%d %d %d\n", pos, x, y);
} else {
printf("2 ");
int x = Rand(, ), y = Rand(1e3, );
if (x > y) swap(x, y);
printf("%d %d\n", x, y);
}
}
}
} const int maxn = 1e5 + ;
struct Seg {
double l1, l2, r1, r2;
}seg[maxn << ];
int n, q;
pii a[maxn]; void push_up(int u) {
seg[u].l2 = seg[lson].l2 * seg[rson].l2 / ( - seg[lson].r1 * seg[rson].l1);
seg[u].l1 = seg[lson].l1 + seg[lson].l2 * seg[lson].r2 * seg[rson].l1 / ( - seg[lson].r1 * seg[rson].l1);
seg[u].r1 = seg[rson].r1 + seg[rson].r2 * seg[rson].l2 * seg[lson].r1 / ( - seg[lson].r1 * seg[rson].l1);
seg[u].r2 = seg[lson].r2 * seg[rson].r2 / ( - seg[lson].r1 * seg[rson].l1);
} double query1(int u, int l, int r, int L, int R);
double query3(int u, int l, int r, int L, int R);
double query4(int u, int l, int r, int L, int R); double query(int u, int l, int r, int L, int R) {
if (l == L && R == r) return seg[u].l2;
int mid = (l + r) >> ;
if (R <= mid) return query(lson, l, mid, L, R);
else if (L >= mid) return query(rson, mid, r, L, R);
double lhs = query(lson, l, mid, L, mid), rhs = query(rson, mid, r, mid, R);
double L1 = query1(rson, mid, r, mid, R), R1 = query3(lson, l, mid, L, mid);
return lhs * rhs / (. - L1 * R1);
} double query3(int u, int l, int r, int L, int R) {
if (l == L && r == R) return seg[u].r1;
int mid = (l + r) >> ;
if (R <= mid) return query3(lson, l, mid, L, R);
else if (L >= mid) return query3(rson, mid, r, L, R);
double tem = query3(rson, mid, r, mid, R);
double R2 = query4(rson, mid, r, mid, R);
double R1 = query3(lson, l, mid, L, mid);
double L2 = query(rson, mid, r, mid, R);
double L1 = query1(rson, mid, r, mid, R);
return tem + R2 * R1 * L2 / (. - L1 * R1);
} double query4(int u, int l, int r, int L, int R) {
if (l == L && r == R) return seg[u].r2;
int mid = (l + r) >> ;
if (R <= mid) return query4(lson, l, mid, L, R);
else if (L >= mid) return query4(rson, mid, r, L, R);
double lhs = query4(lson, l, mid, L, mid) * query4(rson, mid, r, mid, R);
double rhs = query3(lson, l, mid, L, mid) * query3(rson, mid, r, mid, R);
return lhs / (. - rhs);
} double query1(int u, int l, int r, int L, int R) {
if (l == L && R == r) return seg[u].l1;
int mid = (l + r) >> ;
if (R <= mid) return query1(lson, l, mid, L, R);
else if (L >= mid) return query1(rson, mid, r, L, R);
double tem = query1(lson, l, mid, L, mid);
double L1 = query1(rson, mid, r, mid, R);
double L2 = query(lson, l, mid, L, mid);
double R2 = query4(lson, l, mid, L, mid);
double R1 = query3(lson, l, mid, L, mid);
return tem + L2 * L1 * R2 / (. - R1 * L1);
} void build(int u, int l, int r) {
if (r - l < ) {
double p = (double)a[l].first / a[l].nd;
seg[u].l1 = - p;
seg[u].l2 = p;
seg[u].r1 = p;
seg[u].r2 = - p;
return;
}
int mid = (l + r) >> ;
build(lson, l, mid), build(rson, mid, r);
push_up(u);
} void update(int u, int l, int r, int L, int R, int lhs, int rhs) {
if (l == L && r == R) {
double p = (double)lhs / rhs;
seg[u].l1 = - p;
seg[u].l2 = p;
seg[u].r1 = p;
seg[u].r2 = - p;
return;
}
int mid = (l + r) >> ;
if (R <= mid) update(lson, l, mid, L, R, lhs, rhs);
else update(rson, mid, r, L, R, lhs, rhs);
push_up(u);
} double __get(int x, int y) {
return query(, , n + , x, y + );
} void __set(int x, int y, int z) {
update(, , n + , x, x + , y, z);
} int main() {
//data_gen(); return 0;
//C(); return 0;
int debug = ;
if (debug) freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while (~scanf("%d%d", &n, &q)) {
FOR(i, , n) scanf("%d%d", &a[i].first, &a[i].nd);
build(, , n + );
FOR(i, , q) {
int op, x, y, z;
scanf("%d%d%d", &op, &x, &y);
if (op == ) {
z = readint();
__set(x, y, z);
} else {
double ans = __get(x, y);
printf("%.10f\n", ans);
}
}
}
return ;
}
cf 712E Memory and Casinos的更多相关文章
- Codeforces 712E Memory and Casinos
Description There are n casinos lined in a row. If Memory plays at casino \(i\), he has probability ...
- 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 ...
- Memory and Casinos CodeForces - 712E (概率,线段树)
题目链接 题目大意:$n$个点, 每个点$i$有成功率$p_i$, 若成功走到$i+1$, 否则走到走到$i-1$, 多组询问, 求从$l$出发, 在$l$处不失败, 最后在$r$处胜利的概率 设$L ...
- Codeforces Round #370 (Div. 2) E. Memory and Casinos (数学&&概率&&线段树)
题目链接: http://codeforces.com/contest/712/problem/E 题目大意: 一条直线上有n格,在第i格有pi的可能性向右走一格,1-pi的可能性向左走一格,有2中操 ...
- 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 ...
- CF712E Memory and Casinos 期望概率
题意:\(n\)个赌场,每个赌场有\(p_{i}\)的胜率,如果赢了就走到下一个赌场,输了就退回上一个赌场,规定\(1\)号赌场的上一个是\(0\)号赌场,\(n\)号赌场的下一个是\(n + 1\) ...
- 「CF712E」Memory and Casinos「线段树」「概率」
题解 解法1:(官方做法) 一段区间的\(L\)定义为从最左边开始出发,最左不失败,一直到最右边胜利的概率,\(R\)定义为从最右边开始出发,最左不失败,又回到最右边胜利的概率 考虑一个区间\([l, ...
- 【CF712E】Memory and Casinos(数学 期望 DP)
题目链接 大意 给出一个序列,当你在某个点时,有一个向右走的概率\(P_i\)(向左为\(1-P_i\)), 给出\(M\)个操作,操作有两类: 1 X Y Z:把\(P_X\)的值修改为\(\fra ...
- simotion读写CF卡,保存/读取变量
simotion读写CF卡功能 1 使用西门子的Simotion运动控制器时,有时需要用到 读/写 CF卡的功能.主要来自以下几个方面的需求. 1)用户数据量较大,可保持(retain)存储区的容量不 ...
随机推荐
- 获取EMF文件内全部文字, 并按照左上到右下的顺序排序
因为工作要求, 需要对EMF文件文字内容做分析.....SO, 如下代码出现了 懒得加注释了, 反正对外接口属性就那么几个, 根据英文猜吧, 很容易的 说明一下: 这个东西结果会对所有文字内容按照左上 ...
- python jenkins-api,jira crowd. email-servers
jenkins user authentication: http://stackoverflow.com/questions/15411208/authenticate-jenkins-users ...
- 如何编写自己的Arduino库?
一开始写Arduino 的时候很不习惯,没有main函数,因为好多东西都被隐藏了.一直想搞清楚,以便编写自己的库文件.于是研究一下午,下面是一些总结. Arduino工程的初步认识 一.目录规范 当你 ...
- HTTPS 协议和原理
1 HTTPS 协议概述 HTTPS 可以认为是 HTTP + TLS.HTTP 协议大家耳熟能详了,目前大部分 WEB 应用和网站都是使用 HTTP 协议传输的. TLS 是传输层加密协议,它的前身 ...
- 关于CLR、CIL、CTS、CLS、CLI、BCL和FCL
如果要想深入学习.NET平台,那么标题中的这些关键字对你来说并不陌生,这些名词构成了.NET庞大的生态系统,为了宏观认识.NET平台,学些.NET架构体系,针对一些常用常用名词的理解是很有必要的,未必 ...
- ftp应用
ftp的基本应用: 下载easyfzs ftp,仿真模拟ftp服务器. 类库: using System; using System.Collections.Generic; using System ...
- ubifs概述
UBIFS无排序区块图像文件系统(Unsorted Block Image File System, UBIFS)是用于固态存储设备上,并与LogFS相互竞争,作为JFFS2的后继文件系统之一.真正开 ...
- 使用MapReduce实现join操作
在关系型数据库中,要实现join操作是非常方便的,通过sql定义的join原语就可以实现.在hdfs存储的海量数据中,要实现join操作,可以通过HiveQL很方便地实现.不过HiveQL也是转化成 ...
- ps commad
要对系统中进程进行监测控制,查看状态,内存,CPU的使用情况,使用命令:/bin/ps (1) ps :是显示瞬间进程的状态,并不动态连续: (2) top:如果想对进 ...
- MOSS(Microsoft Office Sharepoint Server)升级2013遇到的PDF权限问题及解决方案
最近公司MOSS从2007升级到了2013,遇到了一个很呕心的问题: 为了保护公司资料安全,我们一直使用RMS给文档增加权限(信息权限管理 (IRM)),只有公司内部员工可以阅读.RMS加权限的范围仅 ...