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

本文提供了一种解决CodeForces 820D问题的有效算法。通过预处理每次移动改变符号的个数,实现了O(n)的时间复杂度。文中详细介绍了关键步骤,包括正负项的变化计算及端点处理。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值