BZOJ 2216: [Poi2011]Lightning Conductor
难度在于认识到这个式子有决策单调性,原因在于sqrt(a+x)增长速度不断减慢
单调队列维护函数,二分求交点
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; int n,a[1000005],stack[1000005]; double F[1000005],s[1000005]; double calc(int x,int y){ return s[abs(y-x)]+a[x]; } int check(int x,int y){ int L=max(x,y),R=n; if (calc(x,n)>calc(y,n)) return n+1; while (L<R){ int mid=(L+R)>>1; if (calc(x,mid)<=calc(y,mid)) R=mid; else L=mid+1; } return L; } void solve(){ int head=1,tail=0; for (int i=1; i<=n; i++){ while (tail-head>0 && check(stack[tail-1],stack[tail])>=check(stack[tail],i)) tail--; stack[++tail]=i; while (tail-head>0 && check(stack[head],stack[head+1])<=i) head++; F[i]=max(F[i],calc(stack[head],i)); } } int read(){ char c='-'; while (c<'0' || c>'9') c=getchar(); int ans=0; while (c>='0' && c<='9'){ ans=ans*10+c-'0'; c=getchar(); } return ans; } int main(){ scanf("%d",&n); for (int i=1; i<=n; i++) s[i]=sqrt(i); for (int i=1; i<=n; i++) a[i]=read(); solve(); for (int i=1; i<=n/2; i++) swap(a[i],a[n-i+1]),swap(F[i],F[n-i+1]); solve(); for (int i=n; i>=1; i--) printf("%d\n",max(0,(int)ceil(F[i])-a[i])); return 0; }