[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;
}
本文来自博客园,作者:zhouhuanyi,转载请注明原文链接:https://www.cnblogs.com/zhouhuanyi/p/16983643.html

浙公网安备 33010602011771号