CF-819B. Mister B and PR Shifts(模拟,找规律)

CF传送门

洛谷传送门


解题思路

很容易发现,对于每一次移动,除了最后一位,每一个数对答案的变化的贡献只有两种情况:

  • 若a[i]>=i,对答案的贡献是+1
  • 若a[i]<i,对答案的贡献是-1

所以我们可以预处理出每个时刻从a[i]<i到a[i]>=i的数有多少个,然后动态维护cnt1和cnt2(分别记录当前-1的和+1的数字有几个)。

一定要注意最后一位的处理,很显然最后一位一定是从cnt2中移动到了cnt1中,所以别忘记cnt1++,cnt2--。

细节比较多,一定要注意细节。

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<iomanip>
12 #include<ctime>
13 #include<stack>
14 using namespace std;
15 const int maxn=1000005;
16 int n,a[maxn],k,t[maxn],cnt1,cnt2;
17 long long res,ans;
18 int main()
19 {
20     cin>>n;
21     for(int i=1;i<=n;i++) cin>>a[i];
22     for(int i=1;i<=n;i++){
23         int x=a[i]-i;
24         if(x>0){
25             res+=x;
26             t[x]++;
27             cnt1++;
28         }else{
29             res-=x;
30             t[n+x]++;
31             cnt2++;
32         }
33     }
34     ans=res;
35     for(int i=1;i<=n;i++){
36         res=res-cnt1+cnt2;
37         cnt1=cnt1-t[i];
38         cnt2=cnt2+t[i];
39         res=res-abs(a[n-i+1]-n)+abs(a[n-i+1]-1)-1;
40         cnt1++;
41         cnt2--;
42         if(ans>res) ans=res,k=i;
43     }
44     cout<<ans<<" "<<k;
45     return 0;
46 }

 

posted @ 2021-03-08 00:12  尹昱钦  阅读(45)  评论(0编辑  收藏  举报