Codeforces Round #421 (Div. 1):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;
}