CF1294E Obtain a Permutation 题解

Posted whx666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1294E Obtain a Permutation 题解相关的知识,希望对你有一定的参考价值。

由题意易得每列互不相关,对每列单独考虑

在一列中,有些数本来就是目标状态中这一列的数,可以通过若干次移动操作使其在正确的位置,有些数则只能修改

统计这一列如果移动 k 次(0 <= k <= n - 1)有多少数不需要修改

设第 i 行第 j 列的数为 x,若 x <= n * m && (x - j) % m == 0, 说明 x 在目标状态中是第 j 列第 (x - j) / m + 1 行的数,(注意这里一定要判断x <= n * m,比赛时没判断查了半天也没发现)

可以通过 p = (i - (x - j) / m - 1 + n) % n 次移动操作使 x 在正确的位置(+ n 在 % n 是为了处理负数)并在计数数组 c 中使 c[p]++

最后枚举移动次数 k,这一列需要的步骤 ans = min (k + n - c[k]),并将 ans 累加到最终答案res中

Code

#include <bits/stdc++.h>
using namespace std;
inline void read (int &x) {
    char ch = getchar(); x = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
}
const int N = 2e5 + 10;
int n, m, res, c[N];
vector<int> v[N];
signed main() {
    read (n), read (m);
    int x;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) read (x), v[i].push_back (x);
    for (int j = 1; j <= m; ++j) {
        for (int i = 0; i < n; ++i) c[i] = 0;
        int ans = 1e9, tmp = 0;
        for (int i = 1; i <= n; ++i) {
            int t = v[i][j - 1];
            if ((t - j) % m == 0 && t <= n * m) 
                ++c[(i - (t - j) / m - 1 + n) % n];
        }
        for (int i = 0; i < n; ++i) ans = min (ans, i + n - c[i]);
        res += ans;
    } printf ("%d
", res);
    return 0;
}

以上是关于CF1294E Obtain a Permutation 题解的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 1294E - Obtain a Permutation

[Codeforces #615 div3]1294E Obtain a Permutation

U - Obtain a Permutation CodeForces - 1294E

Obtain a Permutation乱搞

Obtain a Permutation

Codeforces Round #615 (Div. 3) E. Obtain a Permutation