给定一序列,求对于每一个$a_i$的最小非负整数$p_i$,使得$forall j eq i $有$ p_i>=a_j-a_i+ sqrt{|i-j|}$。
绝对值很烦 ,先分左右情况单独做。现在假设j都在i左边,则$ p_{i} = max { a_{j}-a_{i}+ sqrt{i-j} } = max { a_{j}+ sqrt{i-j} } - a_i$。带根号,不易斜率优化,考虑证决策单调性。
假设最优决策为j,j之前的任意决策称之为$j'$,只与$j$有关的项令之为$h[j]=a[j]$,则有
$h[j]+sqrt{i-j} geqslant h[j']+sqrt{i-j'}$ ①
现要证$ h[j]+sqrt{i-j+1} geqslant h[j']+sqrt{i-j'+1}$ ②
即证$ sqrt{i-j+1}-sqrt{i-j} geqslant sqrt{i-j'+1}-sqrt{i-j'}$($②-①$得)
那么把它看成关于$j$的函数看单调性,设$g(j)=sqrt{i-j+1}+sqrt{i-j}$
对其求导。
$g'(j)=[(i-j+1)^{frac{1}{2}}]' - [(i-j)^{frac{1}{2}}]'=-frac{1}{2} (i-j+1)^{-frac{1}{2}} + frac{1}{2} (i-j)^{-frac{1}{2}}=frac{1}{2} (frac{1}{sqrt{i-j}}-frac{1}{sqrt{i-j+1}})$
由$ i-j<i-j+1$知$frac{1}{2} (frac{1}{sqrt{i-j}}-frac{1}{sqrt{i-j+1}}) > 0$则函数$g(j)$单调增,则上不等式成立,满足单调性。
证完决策单调性优化即可。
错误记录:第二次写的时候line37写成l<r了,,丢人。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 9 template<typename T>inline T read(T&x){ 10 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 11 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 12 } 13 const int N=500000+7; 14 struct kochiya_sanae{ 15 int l,r,pos; 16 kochiya_sanae(int l0=0,int r0=0,int pos0=0):l(l0),r(r0),pos(pos0){} 17 }q[N]; 18 db sq[N],f[N],h[N]; 19 int n,l,r; 20 inline void preprocess(){for(register int i=1;i<=n;++i)sq[i]=sqrt((db)i);} 21 inline db calc(int j,int i){return (db)h[j]+sq[i-j];} 22 inline int find_pos(int L,int R,int j,int i){ 23 ++R;int mid; 24 while(L<R){ 25 mid=L+R>>1; 26 if(calc(j,mid)<=calc(i,mid))R=mid; 27 else L=mid+1; 28 } 29 return R; 30 } 31 inline void dp(){ 32 q[l=r=1]=kochiya_sanae(0,n,0); 33 for(register int i=1;i<=n;++i){ 34 if(q[l].r<i)++l;else ++q[l].l; 35 MAX(f[i],calc(q[l].pos,i)-h[i]); 36 while(l<=r&&calc(q[r].pos,q[r].l)<=calc(i,q[r].l))--r; 37 if(r<l)q[r=l]=kochiya_sanae(i,n,i); 38 else{ 39 int k; 40 if(calc(q[r].pos,q[r].r)>calc(i,q[r].r))k=q[r].r+1; 41 else k=find_pos(q[r].l,q[r].r,q[r].pos,i); 42 if(k<=n)q[r].r=k-1,q[++r]=kochiya_sanae(k,n,i); 43 } 44 } 45 } 46 47 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout); 48 read(n);for(register int i=1;i<=n;++i)read(h[i]);h[0]=-3; 49 preprocess();dp();reverse(h+1,h+n+1);reverse(f+1,f+n+1);dp(); 50 for(register int i=n;i;--i)printf("%d ",(int)ceil(f[i])); 51 return 0; 52 }