USACO 201812 白金組T1題解

傳送門

題目大意

奶牛Bessie在一條橫樑上。橫樑有n+2n+2個位置,分別爲0,1, ,n+10,1,\cdots,n+1

Bessie最終得到的錢和她跳下橫樑的位置有關。如果Bessie到達位置00或位置n+1n+1,那麼Bessie將從橫樑的一端掉下,得到00元錢。

當Bessie在位置kk時,她可以決定做以下兩件事之一:

  • 等概率移動到位置k1k-1k+1k+1
  • 跳下橫樑,得到f(k)f(k)元錢。

請求出Bessie從1, ,n1,\cdots,n的每個位置開始,按最優策略期望能得到的錢。

輸入格式

第一行,一個整數n(2n105)n(2\le n\le10^5)。接下來nn行每行一個整數f(1), ,f(n)(1f(k)109)f(1),\cdots,f(n)(1\le f(k)\le10^9)

輸出格式

nn行,第ii行輸出從位置ii開始能得到的錢,乘以10510^5後下取整。

題解

對於位置0,1, ,n+10,1,\cdots,n+1,需要求出Bessie到達該位置時,是移動還是跳下(對於位置00n+1n+1必須跳下)。

對於如圖所示的情形,假設紅色的點l,rl,r選擇跳下,藍色的點l+1, ,r1l+1,\cdots,r-1選擇移動。

ans[i]ans[i]爲從位置ii開始能得到的錢,則有如下方程組:
ans[l]=f(l)ans[i]=ans[i1]+ans[i+1]2(l<i<r)ans[r]=f(r) ans[l]=f(l)\\ ans[i]=\frac{ans[i-1]+ans[i+1]}2(l<i<r)\\ ans[r]=f(r)\\
解得
ans[i]=f(l)×(ri)+f(r)×(il)rl(lir) ans[i]=\frac{f(l)\times(r-i)+f(r)\times(i-l)}{r-l}(l\le i\le r)
即:在平面上,點(i,ans[i])(i,ans[i])(l,f(l))(l,f(l))(r,f(r))(r,f(r))連接構成的線段上!

所以,要想使所有ans[i]ans[i]最大,需要求出點(0,0),(1,f(1)), ,(n,f(n)),(n+1,0)(0,0),(1,f(1)),\cdots,(n,f(n)),(n+1,0)的上凸殼,

然後對於在凸殼上的點選擇跳下,其他點選擇移動即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005;
int n,x[N];
ll f[N];
int main(){
	freopen("balance.in","r",stdin);
	freopen("balance.out","w",stdout);
	scanf("%d",&n);x[0]=1;
	for(int i=1;i<=n;i++)scanf("%lld",&f[i]);
	for(int i=1;i<=n+1;i++){
		int a=x[x[0]],b=x[x[0]-1];
		while(x[0]>1&&(f[i]-f[a])*(i-b)>=(f[i]-f[b])*(i-a)){
			--x[0];
			a=x[x[0]],b=x[x[0]-1];
		}
		x[++x[0]]=i;
	}
	for(int i=1;i<x[0];i++){
		int v=x[i],u=x[i+1];
		for(int j=v;j<u;j++)if(j){
			ll w=f[v]*(u-j)+f[u]*(j-v);
			printf("%lld\n", (ll)floor(w*100000.0/(u-v)) );
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章