1. 程式人生 > >【BZOJ4030】[HEOI2015]小L的白日夢

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

可能 char 排序 bzoj cnblogs 交換 大於 既然 cst

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

題面

BZOJ
洛谷

題解

要求的是最小的不開心連續段的期望。
然後發現自己就不會做了。
然後就可以來抄題解啦。

首先來猜性質:

  • 第一個,一定是按照不高興的概率單調不增的一個序列。
    還是比較容易猜到的,這個證明也不難,首先我們把這個期望的式子給列出來,發現是:
    \[E=\sum_{i=1}^n (1-a_{i-1})a_i\]
    也就是強制在每一段的開頭位置統計,那麽這個位置必定滿足前一天是開心的,且這一天是不開心的。並且因為是單調的,所以滿足\(a_i\ge a_{i+1}\)
    現在假設把某兩個位置交換,假設這兩個位置是\(i,j\),且\(i<j\)

    ,那麽:
    \[\begin{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\)
    那麽兩者的期望的變化量分別是:
    \[\begin{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\n",ans);
    }
    return 0;
}

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