已知一个长度为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\n",ceil(max(p[n-i+1][1],p[i][0]))); }