NC24197. [USACO 2018 Dec P]Balance Beam
描述
Bessie能够通过表演赚到的钱取决于她最终成功跳下平衡木的位置。平衡木上从左向右的位置记为0,1,…,N+1。如果Bessie到达了位置0或是N+1,她就会从平衡木的一端掉下去,遗憾地得不到报酬。
如果Bessie处在一个给定的位置k,她可以进行下面两项中的任意一项:
1. 投掷一枚硬币。如果背面朝上,她前往位置k−1,如果正面朝上,她前往位置k+1(也就是说,每种可能性1/2的概率)。
2. 跳下平衡木,获得f(k)的报酬(1≤f(k)≤10^9)。
Bessie意识到她并不能保证结果能够得到某一特定数量的报酬,这是由于她的移动是由随机的掷硬币结果控制。然而,基于她的起始位置,她想要求出当她进行一系列最优的决定之后,她能够得到的期望报酬(“最优”指的是这些决定能够带来最高可能的期望报酬)。例如,如果她的策略能够使她以1/2的概率获得10的报酬,1/4的概率获得8的报酬,1/4的概率获得0的报酬,那么她的期望报酬为加权平均值10(1/2)+8(1/4)+0(1/4)=7
输入描述
输入的第一行包含N(2≤N≤10^5)。以下N行包含f(1)…f(N).
输出描述
输出N行。第i行输出10^5乘以Bessie从位置ii开始使用最优策略能够获得的报酬的期望值,向下取整。
示例1
输入:
2 1 3
输出:
150000 300000
C++11(clang++ 3.9) 解法, 执行用时: 24ms, 内存消耗: 2964K, 提交时间: 2020-09-07 06:52:37
#include <bits/stdc++.h> typedef long long ll; inline void read(ll&x){ char c11=getchar();x=0;while(!isdigit(c11))c11=getchar(); while(isdigit(c11))x=x*10+c11-'0',c11=getchar(); } const int N=101000,bs=1e5; int n,tp; struct vec{ int x;ll y; inline vec(){} inline vec(const int&X,const ll&Y):x(X),y(Y){} friend inline vec operator - (const vec&A,const vec&B) {return vec(A.x-B.x,A.y-B.y);} friend inline ll operator * (const vec&A,const vec&B) {return A.x*B.y-A.y*B.x;} }p,st[N]; void push(vec p){ while(tp&&(p-st[tp])*(st[tp]-st[tp-1])<=0)--tp; st[++tp]=p; } int main(){ scanf("%d",&n);vec p; for(int i=1;i<=n;++i)p.x=i,read(p.y),p.y*=bs,push(p); push(vec(n+1,0)); for(int i=1,j=0;i<=n;++i){ while(j<tp&&st[j].x<i)++j; if(st[j].x==i)printf("%lld\n",st[j].y); else printf("%lld\n",((st[j].x-i)*st[j-1].y+(i-st[j-1].x)*st[j].y)/(st[j].x-st[j-1].x)); }return 0; }
C++14(g++5.4) 解法, 执行用时: 28ms, 内存消耗: 4364K, 提交时间: 2020-09-07 09:19:19
#include <bits/stdc++.h> const int N=1e5; int n,cnt; struct node{ int x; long long y; node(int a=0,long long b=0){ this->x=a; this->y=b; } node operator - (const node &a) {return node(x-a.x,y-a.y);} long long operator * (const node &a) {return x*a.y-y*a.x;} }jia,s[N+10]; void push(node nw){ while(cnt&&(nw-s[cnt])*(s[cnt]-s[cnt-1])<=0) --cnt; s[++cnt]=nw; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%lld",&jia.y),jia.x=i,jia.y*=N,push(jia); push(node(n+1,0)); for(int i=1,j=0;i<=n;++i){ while(j<cnt&&s[j].x<i) ++j; if(s[j].x==i) printf("%lld\n",s[j].y); else printf("%lld\n",((s[j].x-i)*s[j-1].y+(i-s[j-1].x)*s[j].y)/(s[j].x-s[j-1].x)); }return 0; }