[JSOI2016]
- 考虑本质不同的sqrt(|i-j|)最多有sqrt(n)种
- 相同的可以放到一块算
- 有些小细节需要注意
- 时间复杂度O(n*sqrt(n))
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int inf=1e9;
const int N=1e5+10;
struct node{int v,pos;}blo[N];
int f[N][25],a[N],last,cnt,ans,now,l,r,n;
inline int read(){
int num=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
return num;
}
inline void Print(int x){if(x>9)Print(x/10);putchar(x%10+'0');}
void RMQ(){
rep(i,1,n)f[i][0]=a[i];
rep(len,1,20){
rep(i,1,n){
if(i+(1<<len)-1<=n)
f[i][len]=max(f[i][len-1],f[i+(1<<(len-1))][len-1]);
}
}
}
int query(int l,int r){
int k=0;
while((1<<(k+1))<=r-l+1)k++;
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
n=read();
rep(i,1,n)a[i]=read();
RMQ();
last=0;
rep(i,2,150000){
if(ceil(sqrt(1.0*(i-1)))!=ceil(sqrt(1.0*i))){
blo[++cnt].v=ceil(sqrt(1.0*(i-1)));
blo[cnt].pos=i-1-last;
last=i-1;
}
}
rep(i,1,n){
ans=0,r=i,now=0;
if(r!=1)while(1){
last=r;
r-=blo[++now].pos;
if(r<=1||last<=1){
ans=max(ans,query(1,last-1)+blo[now].v-a[i]);
break;
}else ans=max(ans,query(r,last-1)+blo[now].v-a[i]);
}
l=i,now=0;
if(l!=n)while(1){
last=l;
l+=blo[++now].pos;
if(l>=n){
ans=max(ans,query(last+1,n)+blo[now].v-a[i]);
break;
}else ans=max(ans,query(last+1,l)+blo[now].v-a[i]);
}
Print(ans);puts("");
}return 0;
}
- 最开始写的整体二分T飞了,只能过n<=10000