【USACO 2018 December Contest, Platinum Problem 1】Balance Bea [JZOJ100128] 鱼戏团表演

Description

以下是翻译魔改版题面:

胖头鱼的睿智终于被主人发现了。他被送往鱼戏团进行摸鱼表演。具体地说,他周围有1到n这么多个池子,而他的目的就是逃出鱼戏团。作为胖头鱼,他自然拥有常人所不及的智慧。
通过学习与模仿,他掌握了在池子间跳跃的方法。假设他目前在第i个池子,接下来每一时刻他能选择:
(1)纵身一跃并随机掉进第i+1或第i-1个池子。
(2)在这个池子中运用胖头尝试逃出鱼戏团,获得这个格子的逃脱系数,并结束过程。
胖头鱼是一条冷静睿智的鱼,他总是有计划地行动,所以他给每一个池子估计了一个逃脱系数f[i] (非负整数)。数值越大,逃脱机会越大。
特殊地,跳到第0个或第n+1个池子会导致胖头鱼缺水GG,因此这两个格子的逃脱系数可以视为0。
现在他忙于应付摸鱼表演,希望你能帮他计算从1…n中每个起点开始的最优期望逃脱系数。
注:胖头鱼可以任意选择操作1或2,胖头自然是绝顶聪明的啦。跳到0或n+1后过程直接结束,并获得0的逃脱系数。
n<=1e5,fi<=1e9

Solution

假设 g [ i ] g[i] g[i]为从i开始的答案
显然有 ∀ i ∈ [ 1 , n ] , g [ i ] = m a x ( f [ i ] , g [ i − 1 ] + g [ i + 1 ] 2 ) \forall i\in[1,n],g[i]=max(f[i],{g[i-1]+g[i+1]\over 2}) i[1,n],g[i]=max(f[i],2g[i1]+g[i+1])

显然,如果将(i,g[i])看做平面上的点,那么它一定是凸的
想到这里,就容易发现g[i]就是将所有点(i,f[i])取上凸壳以后剩下的部分,中间的用斜率算即可。

凸壳可以用单调栈维护。
复杂度 O ( n ) O(n) O(n)

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define LL long long
#define N 100005
using namespace std;
int n;
LL a[N],st[N],ans[N];
int main()
{
	cin>>n;
	st[st[0]=1]=0;
	st[++st[0]]=1;
	fo(i,1,n) scanf("%lld\n",&a[i]);
	fo(i,2,n+1)
	{
		while(st[0]>1&&(a[i]-a[st[st[0]]])*(st[st[0]]-st[st[0]-1])>=(a[st[st[0]]]-a[st[st[0]-1]])*(i-st[st[0]])) st[st[0]--]=0;
		st[++st[0]]=i;
	}
	int j=0;
	fo(i,1,n)
	{
		while(st[j+1]<=i) j++;
		if(st[j]==i) ans[i]=a[i]*(LL)100000;
		else
		{
			ans[i]=((double)(a[st[j+1]]-a[st[j]])*(LL)100000/(st[j+1]-st[j])*(i-st[j])+a[st[j]]*(LL)100000+0.00001);
		}
		printf("%lld\n",ans[i]);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值