zoukankan      html  css  js  c++  java
  • 【BZOJ4030】[HEOI2015]小L的白日梦

    【BZOJ4030】[HEOI2015]小L的白日梦

    题面

    BZOJ
    洛谷

    题解

    要求的是最小的不开心连续段的期望。
    然后发现自己就不会做了。
    然后就可以来抄题解啦。

    首先来猜性质:

    • 第一个,一定是按照不高兴的概率单调不增的一个序列。
      还是比较容易猜到的,这个证明也不难,首先我们把这个期望的式子给列出来,发现是:

    [E=sum_{i=1}^n (1-a_{i-1})a_i ]

    也就是强制在每一段的开头位置统计,那么这个位置必定满足前一天是开心的,且这一天是不开心的。并且因为是单调的,所以满足(a_ige a_{i+1})
    现在假设把某两个位置交换,假设这两个位置是(i,j),且(i<j),那么:

    [egin{aligned}Delta=&(1-a_{i-1})a_i+(1-a_i)a_{i+1}+(1-a_{j-1})a_j+(1-a_j)a_{j+1}\ &-(1-a_{i-1})a_j-(1-a_j)a_{i+1}-(1-a_{j-1})a_i-(1-a_i)a_{j+1}\ =&(1-a_{i-1})(a_i-a_j)+(1-a_i)(a_{i+1}-a_{j+1})\ &+(1-a_{j-1})(a_j-a_i)+(1-a_j)(a_{j+1}-a_{i+1})\ =&(a_i-a_j)(a_{j-1}-a_{i-1})+(a_{i+1}-a_{j+1})(a_j-a_i)\ =&(a_i-a_j)(a_{j-1}+a_{j+1}-a_{i-1}-a_{i+1}) end{aligned}]

    显然(Delta=E-E'<0),所以有(E<E'),所以就证明了如果序列是单调不增的话期望是最小的。

    • 第二个结论:选择的一定是按照概率排序之后的一段前缀和一段后缀。
      我一开始猜的以为一定是前缀......
      假设我们选择的是一段前缀([1,i]),一段后缀([j,n])。当然都是按照从大往小的顺序排序之后的结果。然后不考虑在中间选择了一段,考虑在中间选择了一个会怎么样,假设在两次选择中,在中间选择了(x)(y)(x<y)
      那么两者的期望的变化量分别是:

    [egin{aligned} Delta&=(1-a_i)a_x+(1-a_x)a_j-(1-a_i)a_y+(1-a_y)a_j\ &=(1-a_i)(a_x-a_y)+a_j(a_y-a_x)\ &=(a_x-a_y)(1-a_i-a_j) end{aligned}]

    发现((1-a_i-a_j))是定值,那么讨论一下,如果它大于(0),那么((a_x-a_y))一定是越小越好,所以会尽可能靠向(j),反过来一定靠向(i)。那么既然都尽可能靠向了,那么就直接放在一起好啦。

    • 第三个性质:每个东西要么选(1)个,要么全部选掉。除了这两种情况之外的情况最多只可能出现一次。
      首先假装我们不知道这个东西,考虑怎么做,我们可以预处理前缀和后缀的最大贡献,然后枚举一个前缀的端点,那么对于所有后缀而言,找一个最大的贡献就行了。
      但是这样子做不了(1e9),因为你需要枚举端点的确切位置。
      现在我们来考虑这个性质怎么处理,首先没有选完整的最多只会有两块,即前缀的最后一段和后缀的最靠前的一段。
      那么我们这么考虑,假设后缀的最靠前的一段多出来了若干个,那么如果把一个变成前缀的最后一个的变化量是(Delta),那么丢到这一段只剩一个之前,每次往前丢一个贡献都是(Delta),这个很显然。所以可以把后缀的这一段变得只剩一个,然后就符合上面的情况了。

    具体实现我也是抄代码了QwQ。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define MAX 100100
    #define double long double
    const double eps=1e-10;
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Node{double p;int c;}p[MAX];
    bool cmp(Node a,Node b){return a.p>b.p;}
    int n,K;
    int main()
    {
    	int T=read();
    	while(T--)
    	{
    		n=read();K=read();
    		for(int i=1;i<=n;++i)
    		{
    			int x=read(),y=read();
    			p[i].p=1.0*x/y,p[i].c=read();
    		}
    		sort(&p[1],&p[n+1],cmp);
    		int l=1,r=n,t;
    		while(!p[l].c)++l;while(!p[r].c)--r;
    		p[l].c-=1;p[r].c-=1;K-=2;
    		double pl=p[l].p,pr=p[r].p;
    		double ans=0;
    		while(K)
    		{
    			while(!p[l].c)++l;
    			while(!p[r].c)--r;
    			if(1-pl>pr)
    			{
    				if(fabs(pr-p[r].p)>eps)t=1;
    				else t=min(K,p[r].c);
    				ans+=(1-p[r].p)*pr+(t-1)*(1-p[r].p)*p[r].p;
    				K-=t;p[r].c-=t;pr=p[r].p;
    			}
    			else
    			{
    				if(fabs(pl-p[l].p)>eps)t=1;
    				else t=min(K,p[l].c);
    				ans+=(1-pl)*p[l].p+(t-1)*(1-p[l].p)*p[l].p;
    				K-=t;p[l].c-=t;pl=p[l].p;
    			}
    		}
    		ans+=(1-pl)*pr;
    		printf("%.6Lf
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    作业
    第四次作业
    第三次作业
    作业
    第4次作业
    第3次作业,c语言
    第二次作业
    黄义方 作业4
    课堂作业
    第三次作业
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10784556.html
Copyright © 2011-2022 走看看