Topic links:
codeforces 1294E Obtain A Permutation
ideas:
For an array of each column, we considered separately, set the current for the first j
column ( j
from 1
the beginning);
for the first i
number (position i
from 0
the beginning), it should be i * m + j
, so if a number n
is in our target sequence, its location should be (n - j) / m
;
traversing our current sequence to calculate this number is in the target sequence, if you calculate the current should move many times to get to it should be in the position;
the establishment of an array rcd[]
, rcd[i]
meaning is moved i
times can make rcd[i]
the number of recovery;
iterate rcd[]
, Norway calculating i
step where the total time required, i.e. i + n - rcd[i]
, the minimum value of all values;
each column calculated minimum value that is the addition result;
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0; char c;
while(c = getchar(), c < '0' || c > '9');
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
const int maxn = 2e5 + 5;
vector<int> mat[maxn];
inline int get(vector<int> & now, int & c, int & m) {
int n = now.size(), ans = 1 << 30;
vector<int> rcd(n + 1);
for(int & x : rcd) x = 0;
for(int i = 0; i < n; i++) {
int x = now[i] - c, y = x / m;
if(x % m == 0 && y >= 0 && y <= n - 1) ++rcd[(i - y + n) % n]; // the range of y should be noticed
}
for(int i = 0; i < n + 1; i++) ans = min(ans, i + n - rcd[i]);
return ans;
}
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
int n = read(), m = read();
for(int i = 0; i < n; i++) {
mat[i].push_back(0);
for(int j = 1; j <= m; j++) mat[i].push_back(read());
}
int ans = 0;
for(int j = 1; j <= m; j++) {
vector<int> now;
for(int i = 0; i < n; i++) now.push_back(mat[i][j]);
ans += get(now, j, m);
}
cout << ans;
return 0;
}