可以说是一道思路较为简单但细节巨多,非常难调的题,到处各种加加减减与分类讨论,这么一道水题最后我写了一个半点。
首先我们可以想到,我们认为初始状态为
于是我们直接考虑
不难发现这东西思路显然看起来很简单,但是当实现的时候就会发现阴间的地方在哪了。首先我们发现有四种情况,即
具体情况可以自己画一下然后看看代码,还是比较显然的,只是细节太多了。
xxxxxxxxxx
691
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26int P[210000];
27ll d[210000];
28ll ans(LONG_LONG_MAX);
29
30int main(){
31 N = read();
32 for(int i = 0; i <= N - 1; ++i)P[i] = read();
33 for(int i = 0; i <= N - 1; ++i)d[0] += min((i - P[i] + N) % N, (P[i] - i + N) % N);
34 d[1] = -d[0];
35 for(int i = 0; i <= N - 1; ++i)
36 if((P[i] - i + N) % N <= (i - P[i] + N) % N){
37 int dis = (P[i] - i + N) % N;
38 d[1]--, d[dis + 1]++;
39 d[dis + 1]++, d[dis + (N >> 1) + 1]--;
40 d[dis + (N >> 1) + 1 + (N & 1 ? 1 : 0)]--;
41 }else{
42 int dis = (i - P[i] + N) % N;
43 d[1]++, d[(N >> 1) - dis + 1]--;
44 d[(N >> 1) - dis + 1 + (N & 1 ? 1 : 0)]--;
45 d[N - dis + 1]++, d[N - dis + 1]++;
46 }
47 for(int i = 1; i <= N - 1; ++i)d[i] = d[i - 1] + d[i];
48 for(int i = 1; i <= N - 1; ++i)d[i] = d[i - 1] + d[i];
49 for(int i = 0; i <= N - 1; ++i)ans = min(ans, d[i]);
50 printf("%lld\n", ans);
51 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
52 return 0;
53}
54
55template < typename T >
56inline T read(void){
57 T ret(0);
58 int flag(1);
59 char c = getchar();
60 while(c != '-' && !isdigit(c))c = getchar();
61 if(c == '-')flag = -1, c = getchar();
62 while(isdigit(c)){
63 ret *= 10;
64 ret += int(c - '0');
65 c = getchar();
66 }
67 ret *= flag;
68 return ret;
69}
update-2023_01_18 初稿