[USACO18DEC]Balance Beam


題目描述

https://www.luogu.org/problemnew/show/P5155

題解

先考慮這么一個問題,我們設f[i]表示從i點出發,按照題意去走,走到n的概率。

初值f[0]=0(到0相當於死了),f[n]=1(已經到終點了)。

f[i]=(f[i-1]+f[i+1])/2

解得f[x]=x/n

歸納可證:對於點對a,b和中間任意一個i,i的期望為(f(a)*(b-i)+f(b)*(i-a))/(b-a)

然后我們發現一個神奇的事情:我們求得i點的期望就是ab連線上i出的y值。

 

這個算一算就可以出來。

然后這個題期望帶上了權值,其實一個道理,我們求最優解,其實只需要對n個點求凸包計算就好了。

細節:卡精度卡到喪心病狂,不能用點斜式,直接用上面的式子算點值就可以了。

代碼

#include<iostream>
#include<cstdio>
#define N 100002
using namespace std;
typedef long long ll;
ll n,a[N],top;
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
struct point{
    ll x,y;
    point operator -(const point &b)const{return point{x-b.x,y-b.y};};
    double operator *(const point &b)const{return x*b.y-y*b.x;}
}st[N];
int main(){
    n=rd();
    for(int i=1;i<=n;++i)a[i]=rd(),a[i]*=100000;
    st[1]=point{0,0};st[2]=point{1,a[1]};top=2;
    for(int i=2;i<=n+1;++i){
        point x=point{i,a[i]};
        while(top>1&&(st[top]-st[top-1])*(x-st[top-1])>=0)top--;
        st[++top]=x;
    }
    int p=2;
    for(int i=1;i<=n;++i){
        while(st[p].x<i)p++;
        if(st[p].x==i)printf("%lld\n",st[p].y);
        else printf("%lld\n",(st[p].y*(i-st[p-1].x)+st[p-1].y*(st[p].x-i))/(st[p].x-st[p-1].x));
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM