题解:
发现根号里面只有根号种取值
枚举相同的取值,rmq计算最值即可
rmq取log要提前预处理
//RMQ长度预处理 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define max(a,b) ((a>b)?a:b) using namespace std; const int maxn=100009; const int oo=1000000000; int n; int h[maxn]; int lgs[maxn]; int f[maxn][20]; void STinit(){ for(int i=1;i<=n;++i)f[i][0]=h[i]; for(int j=1;j<=19;++j){ for(int i=1;i+(1<<j)-1<=n;++i){ f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } } inline int Querymax(int l,int r){ int k=lgs[r-l+1]; return max(f[l][k],f[r-(1<<k)+1][k]); } int rd(){ int r=0,k=1; char c=getchar(); for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1; for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0'; return r*k; } int main(){ // freopen("light.in","r",stdin); // freopen("light.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i)h[i]=rd(); STinit(); for(int i=1;i<=n;++i)lgs[i]=(int)log2(i+0.5); for(int i=1;i<=n;++i){ int ans=0; for(int j=1;j<=n;++j){ int fla=0; int r=i-(j-1)*(j-1)-1; int l=i-j*j; if(r<=0){ fla=1; }else{ l=max(1,l); ans=max(ans,-h[i]+j+Querymax(l,r)); } l=i+(j-1)*(j-1)+1; r=i+j*j; if(l>n){ fla&=1; }else{ fla=0; r=min(r,n); ans=max(ans,-h[i]+j+Querymax(l,r)); } if(fla)break; } printf("%d ",ans); } return 0; }