luoguP3515
已知一个长度为n的序列a1,a2,...,an。
对于每个1<=i<=n,找到最小的非负整数p满足:
对于任意的j, \(a_j\)<=\(a_i\)+p- \(\sqrt{|i-j|}\)
n<=5*\(10^5\)
考虑j 则需满足对j\(\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)}\)\(\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
对于j>i同理。
在这种\(\mathbf{决策单调性}\)情况下,可以二分+dp。
#include
#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\n",ceil(max(p[n-i+1][1],p[i][0])));
}