Codeforces #282 div 1 C Helping People 题解_html/css_WEB-ITnose

php中文网
发布: 2016-06-24 11:52:14
原创
1311人浏览过

cf 282 c helping people 题解

原题】不贴了。

废话】好久没写博客了。(我不会告诉你我是离线写的)于是来水经验来了。

来源简述】CF 282 C

原题简述】有N(10^5)个人,每个人有初始的钱。再给出M(5000)个操作L,R,P。每次表示L~R这些人有几率P(0

立即学习前端免费学习笔记(深入)”;

算法简述】首先把这些操作建立出树结构(可以借鉴线段树)。节点i表示范围Li~Ri,它的父亲一定包含它,它也包含它的所有子树。为了方便,建立一个L=1,R=N,P=0的无效节点作为根。

观察到M的范围小,我们用f[i][j]表示在节点i表示的范围内,加的钱数的期望(注意原先的钱数可以用RMQ计算出)。至于为什么是最多(注意还是前缀和性质)加了j元的期望。

那么tmp[j]= ∏f[son][mx[i]+j-mx[son]];

mx[o]是原先区间o的最大钱数。

(这里就用到了f的前缀和性质了)

注意到求完后做一步tmp[j]-=tmp[j-1],取消前缀和性质。

然后我们的任务是求出i的所有f值。

MagicStudio
MagicStudio

图片处理必备效率神器!为你的图片提供神奇魔法

MagicStudio 102
查看详情 MagicStudio

那么ans[i][j]=ans[i][j-1]+tmp[j-1]*p[i]+tmp[j]*(1-p[i]);

    ans[i][j-1]:前缀和

    tmp[j-1]*p[i]:由子树中得最大加j-1,且当前也加

tmp[j]*(1-p[i]):由子树中得最大加j,且当前不加

求完了所有的f[i][j]后,我们对于新加的点K,最后的ans满足

ANS=ans[m][0]*mx[m]+Σ (ans[m][i]-ans[m][i-1])*(mx[m]+i);

【*精华所得类似于分治的树形算法。

【代码】

#include<cstdio>#include<algorithm>#include<cmath>#define N 100005#define M 5005using namespace std;struct arr{int l,r;double p;}a[M];int f[N][18],mx[N],used[N],n,i,j,T,m,k;double ans[M][M],tmp[M],ANS;inline int ask(int x,int y){  int len=(int)log2(y-x+1);  return max(f[x][len],f[y-(1<<len)+1][len]);}inline int cmp(const arr &a,const arr &b){return a.r-a.l<b.r-b.l;}int main(){  scanf("%d%d",&n,&m);  for (i=1;i<=n;i++) scanf("%d",&f[i][0]);  for (j=1;j<=17;j++)    for (i=1;i<=n;i++)      T=i+(1<<(j-1)),f[i][j]=max(f[i][j-1],(T<=n)?f[T][j-1]:0);  for (i=1;i<=m;i++)    scanf("%d%d%lf",&a[i].l,&a[i].r,&a[i].p);  a[++m]=(arr){1,n,0};  sort(a+1,a+m+1,cmp);  for (i=1;i<=m;i++)  {    mx[i]=ask(a[i].l,a[i].r);    for (k=0;k<=m;k++) tmp[k]=1.0;    for (j=1;j<i;j++)       if (a[j].l>=a[i].l&&a[j].r<=a[i].r&&!used[j])      {        used[j]=1;        for (k=0;k<=m;k++)          if (mx[i]+k-mx[j]<=m) tmp[k]*=ans[j][mx[i]+k-mx[j]];      }    for (k=m;k;k--)       tmp[k]-=tmp[k-1];    ans[i][0]=(1-a[i].p)*tmp[0];    for (k=1;k<=m;k++)       ans[i][k]=ans[i][k-1]+tmp[k-1]*a[i].p+tmp[k]*(1-a[i].p);    //ans[i][k-1]:加上k-1的期望(ans[i]实质是前缀和性质)     //tmp[k-1]*p[i]:由子树中得最大加k-1,且当前也加    //tmp[k]*(1-p[i]): 由子树中得最大加k,且当前不加  }   ANS=ans[m][0]*mx[m];  for (i=1;i<=m;i++)    ANS+=(ans[m][i]-ans[m][i-1])*(mx[m]+i);  printf("%.10lf",ANS);}
登录后复制

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号