zoukankan      html  css  js  c++  java
  • CF494C Helping People 题解

    Codeforces
    Luogu

    Description.

    有一个长度为 \(n\) 的区间和 \(q\) 个询问。
    对于每个区间有 \(p_i\) 的概率区间 \(+1\),有 \(1-p_i\) 概率 \(-1\)
    问最后最大值的期望。
    保证区间互不相交

    Solution.

    感觉该想到的都想到了
    但是就是最后没做出来

    枚举最大值,发现只可能是 \([mx,mx+q]\) 范围内。
    然后差分,变成求 所有数都 \(\le mx+w\) 的概率。
    然后 dp,表示为 \(x\)\(\le mx+k\) 的概率。
    因为区间不交,所以直接建树,树上 dp。
    转移就考虑所有儿子互不干扰,所以直接乘积即可。
    然后就做完了哈哈哈哈哈哈哈哈

    Coding.

    点击查看 tcl 代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    //枚举最大值,只可能有 5000 个
    //差分,当前答案就是所有数 <= mx 的概率 - 所有数 <= mx-1 的概率
    //关键应该在那个限制:树型结构
    //然后相当于要求所有数 <=mx 的概率,这个相当于就是一个点到根路径上选不超过 k 个的问题
    //发现不能对点来统计概率
    //我们可以用 dp 表示它和它父亲选 k 个的概率
    //然后 dp[x] 就枚举当前这个转移即可
    //发现所有孩子之间是毫不相干的,所以可以直接乘法转移
    typedef long double ld;const int N=100005;int n,m,a[N],bz[N][20],lg[N],st[N],tp,mx[5005];
    struct ${int l,r;ld p;char operator<($ b) {return l<b.l||(l==b.l&&r>b.r);}}q[5005];
    struct edge{int to,nxt;}e[5005];int et,head[5005];ld dp[5005][5005],zy[5005][2];
    inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
    inline int qry(int l,int r) {int g=lg[r-l+1];return max(bz[l][g],bz[r-(1<<g)+1][g]);}
    inline void dfs0(int x,int fa)
    {
    	mx[x]=qry(q[x].l,q[x].r);for(int i=head[x];i;i=e[i].nxt) dfs0(e[i].to,x);
    	dp[x][0]=1-q[x].p;for(int i=0;i<=m;i++) zy[i][0]=zy[i][1]=1;
    	for(int i=head[x];i;i=e[i].nxt) for(int j=0,y=e[i].to;j<=m;j++)
    		zy[j][0]*=dp[y][min(j-mx[y]+mx[x]-1,m)],zy[j][1]*=dp[y][min(j-mx[y]+mx[x],m)];
    	for(int i=0;i<=m;i++) dp[x][i]=(i?q[x].p*zy[i][0]:0)+(1-q[x].p)*zy[i][1];
    	//for(int i=1;i<=m;i++) printf("%.5Lf %.5Lf\n",zy[i][0],zy[i][1]);
    	//for(int i=0;i<=m;i++) printf("%.5Lf%c",dp[x][i],i==m?'\n':' ');
    }
    int main()
    {
    	read(n,m),lg[0]=-1;for(int i=1;i<=n;i++) read(a[i]),bz[i][0]=a[i],lg[i]=lg[i>>1]+1;
    	q[++m]=($){1,n,0};for(int i=1;i<m;i++) read(q[i].l,q[i].r),scanf("%Lf",&q[i].p);
    	for(int j=1;j<=20;j++) for(int i=1;i+(1<<(j-1))<=n;i++) bz[i][j]=max(bz[i][j-1],bz[i+(1<<(j-1))][j-1]);
    	sort(q+1,q+m+1),tp=0;for(int i=1;i<=m;i++) {for(;tp&&q[st[tp]].r<q[i].l;tp--);adde(st[tp],i),st[++tp]=i;}
    	//putchar('\n');for(int i=1;i<=m;i++) printf("%d %d\n",q[i].l,q[i].r);
    	dfs0(1,0);ld rs=0;for(int i=0;i<=m;i++) rs+=(dp[1][i]-(i?dp[1][i-1]:0))*(mx[1]+i);
    	return printf("%.10Lf\n",rs),0;
    }
    
  • 相关阅读:
    京东精益敏捷教练分享:敏捷助力产品创新!
    设计规范 | 详解组件控件结构体系
    Axure响应式进阶
    通讯录表设计
    TEST1
    c#练习四单元总结
    窗体控件应用总结(1)
    .NET(c#理解)
    test2-11
    test1-1
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15369740.html
Copyright © 2011-2022 走看看