链接: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 }