Obtain a Permutation(思维)

You are given a rectangular matrix of size n×mn×m consisting of integers from 11 to 2⋅1052⋅105.

In one move, you can:

choose any element of the matrix and change its value to any integer between 11 and n⋅mn⋅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 (1≤j≤m1≤j≤m) and set a1,j:=a2,j,a2,j:=a3,j,…,an,j:=a1,ja1,j:=a2,j,a2,j:=a3,j,…,an,j:=a1,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=n⋅ma1,1=1,a1,2=2,…,a1,m=m,a2,1=m+1,a2,2=m+2,…,an,m=n⋅m (i.e. ai,j=(i−1)⋅m+jai,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 (1≤n,m≤2⋅105,n⋅m≤2⋅1051≤n,m≤2⋅105,n⋅m≤2⋅105) — the size of the matrix.

The next nn lines contain mm integers each. The number at the line ii and position jj is ai,jai,j (1≤ai,j≤2⋅1051≤ai,j≤2⋅105).

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=n⋅ma1,1=1,a1,2=2,…,a1,m=m,a2,1=m+1,a2,2=m+2,…,an,m=n⋅m (ai,j=(i−1)m+jai,j=(i−1)m+j).

Examples
Input
3 3
3 2 1
1 2 3
4 5 6
Output
6
Input
4 3
1 2 3
4 5 6
7 8 9
10 11 12
Output
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:=8a1,1:=7,a1,2:=8 and a1,3:=9a1,3:=9 then shift the first, the second and the third columns cyclically, so the answer is 66. It can be shown that you cannot achieve a better answer.

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

In the third example, it is enough to shift the second column cyclically twice to obtain a good matrix, so the answer is 22.
又是一个看着挺简单的题目做了很久。
一开始就是类似于暴力做的,结果错了很多次。。
一开始思路的一个误区,我认为执行操作2的一定是一段连续的数字,就像1 4 7这样的,但是这怎么可能呢?有可能两个数字都要移动那么多的位置,但是他们之间的数字不是这样的,这就要贪心取最优了。
这道题目,每一列是独立的,所以我们应该每一列单独去考虑。对于每一列中的,如果可以移动相同的次数,我们应该归并到一起来计算,这样就可以统计出移动次数0~n-1之间各有多少个数字。每一列这样贪心取最优,就可以了。
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define inf 2e6;
using namespace std;

const int maxx=2e5+100;
vector<int> p[maxx];
int a[maxx];
int n,m;

int main()
{
	scanf("%d%d",&n,&m);
	int x;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		scanf("%d",&x);
		p[i].push_back(x); 
	}
	int ans=0;
	for(int j=0;j<m;j++)
	{
		for(int i=0;i<n;i++) a[i]=0;
		for(int i=1;i<=n;i++)
		{
			if(p[i][j]<=n*m&&(p[i][j]-1)%m==j)
			{
				int tt=p[i][j]/m+(p[i][j]%m?1:0);
				a[(i+n-tt)%n]++;
				//cout<<(i+n-tt)%n<<endl;
			}
		}
		int _min=inf;
		for(int i=0;i<n;i++) _min=min(_min,n-a[i]+i);
		ans+=_min;
	}
	cout<<ans<<endl;
}

努力加油a啊,(o)/~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值