Loading

[JSOI2016]灯塔

链接:https://www.luogu.com.cn/problem/P5503

题目描述:对于每一个\(i\),求出\(h_{j}-h_{i}+\lceil\sqrt|i-j|\rceil\)的最大值。

题解:令第\(i\)个数的答案为\(dp_{i}\),打表可以发现\(h\)具有决策单调性。这一类决策单调性可以采用整体二分的方式求得决策点范围,由于决策点可能相同,所以不能先取整。

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
double dp[1000001],dp2[1000001],f[1000001];
long long h[1000001],n,p[1000001],p2[1000001];
void solve(int l,int r,int L,int R)
{
	int mid=(l+r)/2;
	for (int i=R;i>=L;--i)
		if (i<mid&&h[i]+f[mid-i]>dp[mid])
		{
			dp[mid]=h[i]+f[mid-i];
			p[mid]=i;
		}
	if (l==r)
		return; 
	solve(l,mid,L,p[mid]);
	solve(mid+1,r,p[mid],R);
	return;
}
void solve2(int l,int r,int L,int R)
{
	int mid=(l+r)/2;
	for (int i=R;i>=L;--i)
		if (i>mid&&h[i]+f[i-mid]>dp2[mid])
		{
			dp2[mid]=h[i]+f[i-mid];
			p2[mid]=i;
		}
	if (l==r)
		return;
	solve2(l,mid,L,p2[mid]);
	solve2(mid+1,r,p2[mid],R);
	return;
}
int main()
{
	cin>>n;
	for (int i=1;i<=n;++i)
	{ 
		cin>>h[i];
		dp[i]=-1e18;
	}
	for (int i=1;i<=n;++i)
		f[i]=sqrt(i);
	solve(1,n,1,n);
	solve2(1,n,1,n);
	for (int i=1;i<=n;++i)
		cout<<(int)(ceil(max(max(dp[i],dp2[i])-h[i],(double)(0))))<<endl;
	return 0;
}
posted @ 2022-12-14 21:29  zhouhuanyi  阅读(27)  评论(0)    收藏  举报