【数学期望】Gym 101137LLazy Coordinator

来源:互联网 发布:远走高飞网络歌曲 编辑:程序博客网 时间:2024/06/06 19:32

Problem Description

给你n个事件,接下来2*n行,给你任何事件可能的开始时间,和任何事件可能的结束时间。
让你输出每个事件存在时间的数学期望

思路:

这道题有两个核心点。
一:算期望的时候,事件时间差 两两相减的话,O(n*n)会超时。我们需要对公式进行处理。我们拿例子来说明把。
例如样例
3
+ 4
+ 10
- 11
+ 16
- 20
- 100
对于4这个事件存在时间的期望 = (11-4) * 0.5 + (20-4) * 0.25 + (100 - 4) * 0.25 = 11 * 0.5 + 20 * 0.25 + 100 * 0.25 - 4 * (0.5 + 0.25 + 0.25)。因为对于一个事件,概率和等于1。所以式子等于 11 * 0.5 + 20 * 0.25 + 100 * 0.25 - 4
二: 如何处理对于每个事件的 结束时间的期望也就是这个式子11 * 0.5 + 20 * 0.25 + 100 * 0.25。对于事件4这个式子其实是 11*0.5 + 20*0.5*0.5 + 100*0.5*0.5*1 对于事件16这个式子就变成了20*0.5 + 100*0.5
正着求,有点小复杂(我一开始就是正着,没能敲出来,看了学长的代码发现倒着贼方便),倒着求,详细看代码

#include<bits/stdc++.h>using namespace std;#define maxn 200008int t[maxn], Count[maxn];int vis[maxn];double ans[maxn];int main(){    int n, i;    char s[10];    while(~scanf("%d", &n))    {        memset(Count, 0, sizeof(Count));//记录到这个i点,有多少正在开始的事件        memset(vis, 0, sizeof(vis));        for(i = 1; i <= 2*n; i++)        {            scanf("%s %d", s, &t[i]);            if(s[0] == '+') {                vis[i] = 1;                Count[i] = Count[i-1] + 1;            }            else Count[i] = Count[i-1] - 1;        }        double sum = 0;        int k;        for(i = 2*n; i >= 1; i--)//倒着求ans[]数组,也就是上面强调的式子        {            if(!vis[i])            {                k = Count[i] + 1;                sum = sum*(1-1.0/k) + 1.0*t[i]/k;            }            else            {                ans[i] = sum;            }        }        for(i = 1; i <= 2*n; i++)        {            if(vis[i])                printf("%.10lf\n", ans[i] - t[i]);        }    }    return 0;}