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