您的位置:首页 > 其它

【jzoj5343】【NOIP2017模拟9.3A组】【健美猫】

2017-09-03 16:30 555 查看

description



solution

可以把点投射到以i坐标为x坐标,以a[i]为y坐标的二维平面,考虑维护两条斜率为1直线,点到直线竖直距离和即为答案,分别为维护多少个点在直线上,用两个桶维护即可,坐标分别为到y=x竖直距离和到(n,0)曼哈顿距离。

code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define ULL unsigned LL
#define fo(i,j,k) for(LL i=j;i<=k;i++)
#define fd(i,j,k) for(LL i=j;i>=k;i--)
#define fr(i,j) for(LL i=begin[j];i;i=next[i])
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: