description
solution
可以把点投射到以i坐标为x坐标,以a[i]为y坐标的二维平面,考虑维护两条斜率为1直线,点到直线竖直距离和即为答案,分别为维护多少个点在直线上,用两个桶维护即可,坐标分别为到y=x竖直距离和到(n,0)曼哈顿距离。
code
using namespace std;
LL const mn=4*1e6+2,inf=1e9+7;
LL n,a[mn],cnt[mn],cn2[mn];
LL read(){
char ch=getchar();
while((ch!='-')&&((ch<'0')||(ch>'9')))ch=getchar();
LL op,v=0;
if(ch=='-')op=-1;
else op=1,v=ch-'0';
ch=getchar();
while((ch>='0')&&(ch<='9'))v=v*10+ch-'0',ch=getchar();
return op*v;
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
n=read();
fo(i,1,n)a[i]=read();
LL up=0,tmp=0;
fo(i,1,n){
tmp+=abs(a[i]-i);
if(a[i]>i)cnt[a[i]-i]++;
up+=a[i]>i;
}
LL ans=tmp,up2=0;
fd(i,n,2){
tmp+=i-1-up*2;
up-=cnt[n-i+1];
tmp+=a[i]+1-abs(a[i]-n-1);
cn2[a[i]+n-i]++;
up2++;
tmp+=n-i+1-up2*2;
up2-=cn2[n-i+1];
ans=min(ans,tmp);
}
printf("%lld",ans);
return 0;
}