已知一个长度为n的序列a1,a2,...,an。
对于每个1<=i<=n,找到最小的非负整数p满足:
对于任意的j, (a_j)<=(a_i)+p- (sqrt{|i-j|})
n<=5*(10^5)
考虑j<i的方面
则需满足对j<i a[j]<=a[i]+p-(sqrt{i-j}) , 即:a[j]+(sqrt{i-j}) <=a[i]+p
设g是决策点 即 a[g]+(sqrt{i-g})<=a[i]+p这个g是求出(ans_p)的那个g
所以 对于任意正整数k 有 a[g-k]+(sqrt{i-(g-k)})<=a[g]+(sqrt{i-g})
所以:
那么对于 询问的点i+1
有: a[g-k]+(sqrt{i+1-(g-k)})<a[g]+(sqrt{i+1-g}) 【1】
因为: (sqrt{i+1-(g-k)})-(sqrt(i-(g-k)))<(sqrt{i+1-g})-(sqrt{i-g})
因为: 对于sqrt函数,数值越大 斜率越小,即是 数值越大 因变量+1增加的函数值越小
对于【1】有结论:i点的 所有g-k 均不是i+1的决策点 (因为‘<’,所以肯定在i+1时 g点比g-k优)
所以在j<i的条件下 对于i+1的决策点的位置 总是在i的决策点位置之后
对于j>i同理。
在这种(mathbf{决策单调性})情况下,可以二分+dp。
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=5e5+50;
//决策单调性优化dp 斜率优化
int a[maxn];
double p[maxn][2];
inline void solve(int l,int r,int L,int R,bool ju)
{
if(l>r)return;
int mid=(l+r)>>1,id=mid;
for(int i=L;i<=min(mid,R);i++)
{
if(a[i]>1.0*a[mid]+1.0*p[mid][ju]-sqrt(abs(mid-i)))
{
p[mid][ju]=1.0*a[i]-1.0*a[mid]+sqrt(abs(mid-i));
id=i;
}
}
solve(l,mid-1,L,id,ju);solve(mid+1,r,id,R,ju);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
solve(1,n,1,n,0);
for(int i=1;i<=n/2;i++)swap(a[i],a[n+1-i]);
solve(1,n,1,n,1);
for(int i=1;i<=n;i++)
printf("%.0f
",ceil(max(p[n-i+1][1],p[i][0])));
}