Obtain a Permutation

You are given a rectangular matrix of size n×mn×m consisting of integers from 11 to 21052⋅10^5.

In one move, you can:

choose any element of the matrix and change its value to any integer between 11 and nmn⋅m, inclusive;
take any column and shift it one cell up cyclically (see the example of such cyclic shift below).
A cyclic shift is an operation such that you choose some jj (1jm)(1≤j≤m) and set a1,j:=a2,j,a2,j:=a3,j,,an,j:=a1,ja_{1,j}:=a_{2,j},a_{2,j}:=a_{3,j},…,a_{n,j}:=a_{1,j} simultaneously.
在這裏插入圖片描述
Example of cyclic shift of the first column
You want to perform the minimum number of moves to make this matrix look like this:
在這裏插入圖片描述

In other words, the goal is to obtain the matrix, where a1,1=1,a1,2=2,,a1,m=m,a2,1=m+1,a2,2=m+2,,an,m=nm(ai,j=(i1)m+j)a_{1,1}=1,a_{1,2}=2,…,a_{1,m}=m,a_{2,1}=m+1,a_{2,2}=m+2,…,a_{n,m}=n⋅m (a_{i,j}=(i−1)m+j) with the minimum number of moves performed.

Input
The first line of the input contains two integers nn and mm (1n,m2105,nm2105)(1≤n,m≤2⋅10^5,n⋅m≤2⋅10^5) — the size of the matrix.

The next n lines contain m integers each. The number at the line ii and position jj is ai,j(1ai,j2105)a_{i,j} (1≤a_{i,j}≤2⋅10^5).

Output
Print one integer — the minimum number of moves required to obtain the matrix, where a1,1=1,a1,2=2,,a1,m=m,a2,1=m+1,a2,2=m+2,,an,m=nm(ai,j=(i1)m+j)a_{1,1}=1,a_{1,2}=2,…,a_{1,m}=m,a_{2,1}=m+1,a_{2,2}=m+2,…,a_{n,m}=n⋅m (a_{i,j}=(i−1)m+j).

Examples

inputCopy
3 3
3 2 1
1 2 3
4 5 6
outputCopy
6
inputCopy
4 3
1 2 3
4 5 6
7 8 9
10 11 12
outputCopy
0
input
3 4
1 6 3 4
5 10 7 8
9 2 11 12
output
2

Note
In the first example, you can set a1,1:=7,a1,2:=8a_{1,1}:=7,a_{1,2}:=8 and a1,3:=9a_{1,3}:=9 then shift the first, the second and the third columns cyclically, so the answer is 6. It can be shown that you cannot achieve a better answer.

In the second example, the matrix is already good so the answer is 0.

In the third example, it is enough to shift the second column cyclically twice to obtain a good matrix, so the answer is 2.
顯然列與列之間互不影響,因此只需單獨考慮每一列的最小操作數,然後求和即可。
spd[i]spd[i]爲移動ii步所需的最小花費,初始狀態spd[i]=n+ii[0,n1]spd[i]=n+i\quad\forall i\in\mathbb [0,n-1]
loc[i]loc[i]爲數值ii最終所在的行數。
對於第jj列的每一行ii,如果最終狀態中該列存在元素a[i][j]a[i][j],則更新spd[(iloc[a[i][j]]+n)modn]=spd[(iloc[a[i][j]]+n)modn]1spd[(i-loc[a[i][j]]+n)\bmod n]=spd[(i-loc[a[i][j]]+n)\bmod n]-1,最終更新ans=ans+min(spd[i])i[0,n1]ans=ans+min(spd[i])\quad\forall i\in\mathbb [0,n-1]

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e5 + 10;
int n, m, spd[N];
mii loc;
vi a[N];

inline void init(int j) {
    repi(i, 0, n - 1)spd[i] = i + n;
    loc.clear();
    repi(i, 1, n)loc[(i - 1) * m + j] = i;
}

int main() {
    n = qr(), m = qr();
    repi(i, 1, n)repi(j, 1, m)a[i].pb(qr());
    int ans = 0;
    repi(i, 0, m - 1) {
        init(i + 1);
        repi(j, 1, n)
            if (loc[a[j][i]])
                spd[(j - loc[a[j][i]] + n) % n]--;
        int mn = INF;
        repi(j, 0, n - 1)mn = min(mn, spd[j]);
        ans += mn;
    }
    pi(ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章