codeforces 819B - Mister B and PR Shifts(思维)

原题链接:http://codeforces.com/problemset/problem/819/B

 

题意:把一个数列整体往右移k位(大于n位置的数移动到数列前端,循环滚动),定义该数列的“偏差值”:

求在移动最少k位时,得到的最小“偏差值”。

 

思路:对于每个数每次往右移,其与i的差值-1,差值记为d,那么记录d>0和d<=0的位置个数;同时记录每个大于0的d的个数,保存在po数组内。

每次往右移,sum加上d<=0的个数,减去d>0的个数,对于将要移动到数列首位置的数,更新差值,进行特判,并更新po数组。

 

AC代码:

 1 #include
 2 #include
 3 #include
 4 #include
 5 using namespace std;
 6 const int MAXN = 2e6 + 10;
 7 int a[MAXN], cnt_ne = 0, cnt_po = 0, d[MAXN];
 8 int ne[MAXN], po[MAXN];
 9 long long sum = 0;
10 int main()
11 {
12     int n;
13     scanf("%d", &n);
14     memset(ne, 0, sizeof(ne));
15     memset(po, 0, sizeof(po));
16     for (int i = 0;i) {
17         scanf("%d", &a[i]);
18         d[i] = a[i] - i-1;
19         if (d[i]>0) {
20             cnt_po++;
21             po[d[i]]++;
22         }
23         else {
24             cnt_ne++;
25             ne[-d[i]]++;
26         }
27         sum += abs(d[i]);
28     }
29     int u = 0;
30     long long res = sum;
31     for (int i = 1;i) {
32         //cout << sum << endl;
33         sum += cnt_ne;
34         sum -= cnt_po;
35         cnt_po -= po[i];
36         cnt_ne += po[i];
37 
38         d[n - i] -= i - 1;//最后一个数更新差值
39                           //再放到第一位,进行判断
40         if (d[n - i] <= 0) {
41             if (d[n - i] + n - 1>0) {
42                 int dd = d[n - i] + n - 1 - (abs(d[n - i])+1);
43                 d[n - i] += n - 1;
44                 sum += dd;
45 
46                 cnt_po++;
47                 cnt_ne--;
48                 po[d[n - i] + i]++;
49             }
50             else sum -= n;
51         }else sum += n - 2;
52         
53         if (res>sum) {
54             res = sum;
55             u = i;
56         }
57     }
58     cout << res << ' ' << u << endl;
59 }

 

转载于:https://www.cnblogs.com/MasterSpark/p/7622466.html

你可能感兴趣的:(codeforces 819B - Mister B and PR Shifts(思维))