codeforces712E Memory and Casinos(区间树)

题意:

有n个赌场,你在i赌场时,有pi的概率走到i+1,有1−pi的概率走到i−1.保证任何时候pi≤pi+1
有q次操作,修改一个赌场的p值;或者询问[l,r]表示从第l个赌场走到r的概率,他在走的过程中不会离开区间[l,r].

要点:

比较容易看出是区间树,但是这个概率的处理很复杂,基本思路可以参考下面这个博客:

参考博客:点击打开链接

但是这个博客还有网上我找了一下,有一个地方都没有解释,就是最后结果应该是:

f[l]/f[r]=(g[1]+g[2]...g[l])/(g[1]+g[2]...g[r])=g[1]*(1+t1+t1*t2+...)/(g[1]*((1+t1+t1*t2+...))=(1+t1+t1*t2+...t1*t2..tl)/(1+t1+t1*t2+...t1*t2*tl)=1+(tl+tl*tl+1...)

最后用区间树维护一下即可。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 100005;
struct segtree
{
	double a, b;
}seg[4*maxn],now;
double p[maxn];
int n, q;

void build(int l, int r, int pos)
{
	if (l == r)
	{
		seg[pos].a = seg[pos].b = (1 - p[l]) / p[l];
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, pos*2);
	build(mid+1, r, pos * 2 + 1);
	seg[pos].a = seg[2 * pos].a*seg[2 * pos + 1].a;
	seg[pos].b = seg[2 * pos].b + seg[2 * pos].a*seg[2 * pos + 1].b;
}
void query(int l, int r, int x, int y, int pos)
{
	if (l == x&&r == y)
	{
		now.b = now.b + now.a*seg[pos].b;
		now.a = now.a*seg[pos].a;
		return;
	}
	int mid = (l + r) / 2;
	if (y <= mid) 
		query(l, mid, x, y, pos * 2);
	else if (x > mid) 
		query(mid + 1, r, x, y, pos * 2 + 1);
	else
	{
		query(l, mid, x, mid, pos * 2);
		query(mid + 1, r, mid + 1, y, pos * 2 + 1);
	}
}
void update(int l, int r, int pos, int x)
{
	if (l == r)
	{
		seg[pos].a = seg[pos].b = (1 - p[l]) / p[l];
		return;
	}
	int mid = (l + r) / 2;
	if (x <= mid)
		update(l, mid, 2 * pos, x);
	else
		update(mid+1, r, 2 * pos + 1, x);
	seg[pos].a = seg[2 * pos].a*seg[2 * pos + 1].a;
	seg[pos].b = seg[2 * pos].b + seg[2 * pos].a*seg[2 * pos + 1].b;
}

int main()
{
	int a, b;
	cin >> n >> q;
	for (int i = 1; i <= n; i++)
	{
		cin >> a >> b;
		p[i] = 1.0*a/b;
	}
	build(1, n, 1);
	while (q--)
	{
		int order, x, y,z;
		cin >> order;
		if (order == 2)
		{
			cin >> x >> y;
			now.a = 1;
			now.b = 0;
			query(1, n, x, y, 1);
			double ans;
			if (now.b <= 1e15)
				ans = 1 / (1 + now.b);
			else
				ans = 0;
			printf("%.10lf\n", ans);
		}
		else
		{	
			cin >> x >> y >> z;
			p[x] = 1.0*y/z;
			update(1, n, 1, x);
		}
	}
	return 0;
}


posted @ 2016-11-25 21:51  seasonal  阅读(72)  评论(0编辑  收藏  举报