Codeforces Round #421 (Div. 1) B. Mister B and PR Shifts 模拟

链接:

http://codeforces.com/contest/819/problem/B

题意:

有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因为最后一个数跑到了第一个

代码:

31 int n;
32 int p[MAXN];
33 int cur[MAXN * 2];
34 
35 int main() {
36     ios::sync_with_stdio(false), cin.tie(0);
37     cin >> n;
38     int L = 0, R = 0;
39     ll sum = 0;
40     rep(i, 1, n + 1) {
41         cin >> p[i];
42         sum += abs(p[i] - i);
43         if (p[i] >= i) L++, cur[p[i] - i]++;
44         else R++;
45     }
46     ll ans = sum;
47     int pos = 0;
48     rep(i, 0, n - 1) {
49         L -= cur[i];
50         R += cur[i];
51         sum = sum - L + R - abs(p[n - i] - n - 1) + p[n - i] - 1;
52         cur[p[n - i] + i]++;
53         L++, R--;
54         if (sum < ans) ans = sum, pos = i + 1;
55     }
56     cout << ans << ' ' << pos << endl;
57     return 0;
58 }
原文地址:https://www.cnblogs.com/baocong/p/7364309.html