cf round #421 div2 D. Mister B and PR Shifts

链接:http://codeforces.com/contest/820/problem/D

分析:|p[i]-i|每次只会变化1,先不考虑端点情况,就只有p[i]==i的时候变化,每次k+1的时候,对于正项,答案-1,负向+1,因此可以预处理每次移动改变符号的个数,单独处理下端点,就可以更新答案,复杂度为O(n)。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn=1e6+5;
 5 int p[maxn],countp=0,countn=0,mink,k,n;
 6 long long sum,ans;
 7 int idx[maxn];
 8 int ABS(int n){
 9     if(n>=0)return n;
10     return -n;
11 }
12 int main(){
13     memset(idx,0,sizeof(idx));
14     scanf("%d",&n);
15     for(int i=1;i<=n;i++)scanf("%d",&p[i]);
16     //预处理第k次变号的下标及正负个数
17     for(int i=1;i<=n;i++){
18         idx[(p[i]-i+n)%n]++;
19         if(p[i]>i)countp++;
20         if(p[i]<=i)countn++;
21         sum+=ABS(p[i]-i);
22     }
23     mink=0;ans=sum;
24     for(int k=1;k<n;k++){
25         sum=sum+countn-1-countp;
26         sum+=2*p[(n-k)%n+1]-1-n;
27         countp++;countn--;
28         countp-=idx[k];
29         countn+=idx[k];
30         if(sum<ans){
31             mink=k;ans=sum;
32         }
33     }
34     cout<<ans<<' '<<mink<<endl;
35     return 0;
36 }
原文地址:https://www.cnblogs.com/7391-KID/p/7091067.html