Codeforces Round #421 (Div. 1):B. Mister B and PR Shifts(瞎搞)

 

B. Mister B and PR Shifts

time limit per test 2 seconds

memory limit per test 256 megabytes

input standard input

output standard output

Some time ago Mister B detected a strange signal from the space, which he started to study.

After some transformation the signal turned out to be a permutation p of length n or its cyclic shift. For the further investigation Mister B need some basis, that's why he decided to choose cyclic shift of this permutation which has the minimum possible deviation.

Let's define the deviation of a permutation p as .

Find a cyclic shift of permutation p with minimum possible deviation. If there are multiple solutions, print any of them.

Let's denote id k (0 ≤ k < n) of a cyclic shift of permutation p as the number of right shifts needed to reach this shift, for example:

  • k = 0: shift p1, p2, ... pn,
  • k = 1: shift pn, p1, ... pn - 1,
  • ...,
  • k = n - 1: shift p2, p3, ... pn, p1.

Input

First line contains single integer n (2 ≤ n ≤ 106) — the length of the permutation.

The second line contains n space-separated integers p1, p2, ..., pn (1 ≤ pi ≤ n) — the elements of the permutation. It is guaranteed that all elements are distinct.

Output

Print two integers: the minimum deviation of cyclic shifts of permutation p and the id of such shift. If there are multiple solutions, print any of them.

Examples

input

3
1 2 3

output

0 0

input

3
2 3 1

output

0 1

input

3
3 2 1

output

2 1

 

 

题意:

有n个数,从1到n乱序排列,定义这n个数的秩序值为∑(a[i]-i) (1<=i<=n), 你每次将这个数组向右循环移位p次,问p等于多少时,这n个数的秩序值最小?

 

记录下每个数是在目标位置的左边还是右边,存下所有在目标左边的数,

cur[i]表示初始数组中有多少个数在它目标左边第i个位置上

->注意要存下一开始在目标左边(包括在目标上)的个数L,以及目标右边的数的个数r

 

之后直接模拟右移,对于第i次右移,L = L-cur[i-1],   r = r+cur[i-1],即当次位移刚好有cur[i-1]个数原本在目标位置左边及目标上跑到了目标位置的右边,

每次的秩序值便是初始秩序值-L+r+特判最后一个数移到第一个数所产生的影响

但注意计算之后L还要+1,r还要-1因为最后一个数跑到了第一个

 

复杂度O(n)

 

 

#include<stdio.h>
#include<stdlib.h>
#define LL long long
int p[1000005], cur[2000005];
int main(void)
{
	LL ans, sum;
	int n, L, r, i, temp;
	scanf("%d", &n);
	sum = L = r = temp = 0;
	for(i=1;i<=n;i++)
		scanf("%d", &p[i]);
	for(i=1;i<=n;i++)
	{
		sum += abs(p[i]-i);
		if(p[i]>=i)  L++, cur[p[i]-i]++;
		else  r++;
	}
	ans = sum;
	for(i=0;i<n-1;i++)
	{
		L -= cur[i]; r += cur[i];
		sum = sum-L+r-abs(p[n-i]-n-1)+p[n-i]-1;
		cur[p[n-i]+i]++;
		L++, r--;
		if(sum<ans)
			ans = sum, temp = i+1;
	}
	printf("%lld %d\n", ans, temp);
	return 0;
}

 

 

 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值