题意:
给一个 n×m 的矩阵,你想要把它还原成如下的矩阵
你有两种操作:
• 选择一个数,修改它的值。
• 选择一列,每个元素上移一位,第一行的元素移到第 n 行。
求还原的最小操作次数。
数据范围:
1≤n,m≤2⋅10^5
1≤n⋅m≤2⋅10^5
思路:
对于任意一行,我们可以发现,无论是先进行单点修改,后进行整列上移,还是先进行整列上移,后进行单点修改。都是没有影响的,两种操作是互相独立的。所以我们可以设定samej,i表示第j列上移i个单位后,有多少个数是不需要改变的,这时我们可以得到对于任意一列,操作次数是n-samej,i+i,因为n-samej,i是需要改变的操作次数,i是上移的次数,所以对于任意一列,最优答案就为min(0≤i<n)(n-samej,i+i)。所以最终整体答案为所有列最优答案的求和。这时我们就只需要求出same即可,在判断ai,j是否属于第j列的数字时,有三个条件:j≤ai,j , ai,j≤m*n , (ai,j-j) % m = 0.满足这三个条件,就可以说明ai,j是第j列的数字。然后我们还需要判断ai,j应该在第几行,我们设ai,j应该在第k行。通过还原后的矩阵得到公式k=(ai,j-j)/m+1。最后判断当前列和第k列的位置,如果k≤i,就same[i-k]++,如果k>i,就same[i-k+n]++.最后通过最上面的公式求得答案即可。
代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5