JZOJ 5343. 【NOIP2017模拟9.3A组】健美猫

题面


其中 \(1 \leq n \leq 2 \times 10^6\)

分析

考虑每次移动,发现负数对答案贡献少 \(1\),非负数多 \(1\)
每次移动都加了 \(1\)
负数变非负数关键点在于 \(0\)
把所有值映射到数轴上,每次加一相当于原点向左移一位
讨论移位后负数数量的变化即可
首位则特别处理
我们只需要记录负数的情况(见 \(f\)

\(Code\)

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long LL;

const int N = 4e6 + 5;
int n , s1 , s2 , s[N] , f[N];
LL ans , sum;

int main()
{
	scanf("%d" , &n);
	for(register int i = 1; i <= n; i++)
	{
		scanf("%d" , &s[i]);
		if (s[i] - i < 0) f[i - s[i]]++ , s2++;
		ans += abs(s[i] - i);
	}
	s1 = n - s2 , sum = ans;
	for(register int i = 1; i < n; i++)
	{
		sum += s1 - s2 - 1 - (s[i] - 1) + abs(s[i] - n);
		s2 -= f[i] , s1 += f[i];
		if (s[i] - n < 0) ++s2 , --s1 , ++f[n - s[i] + i];
		ans = min(ans , sum);
	}
	printf("%lld\n" , ans);
}
posted @ 2020-10-07 22:10  leiyuanze  阅读(90)  评论(0编辑  收藏  举报