难度在于认识到这个式子有决策单调性,原因在于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;
}
BZOJ 2216: [Poi2011]Lightning Conductor
原文:https://www.cnblogs.com/silenty/p/9818672.html