Codeforces 1294E Obtain a Permutation

Description

描述

给一个 n×m 的矩阵,你想要把它还原成如下的矩阵:

你有两种操作:

  • 选择一个数,修改它的值。
  • 选择一列,每个元素上移一位,第一行的元素移到第 n 行。

求还原的最小操作次数。

输入

第一行两个正整数 n,m1n,m2×105n×m2×105)。

接下来是一个 n×m 的矩阵 ai,j1ai,j2×105)。

输出

一个数表示答案。

样例

输入1

3 3
3 2 1
1 2 3
4 5 6

输出1

6

输入2

4 3
1 2 3
4 5 6
7 8 9
10 11 12

输出2

0

输入3

3 4
1 6 3 4
5 10 7 8
9 2 11 12

输出3

2

解释

样例1:a1,17a1,28a1,39,然后每列上移一次。

样例2:矩阵已经还原。

样例3:上移第 22 次。

Solution

先观察一下两种操作:

  • 单点修改
  • 整列上移

发现了什么?不同列之间互不影响,所以我们可以对于每一列分开处理。

那么,对于一列 j,因为“先修改,后上移”和“先上移,后修改”没有本质区别,所以我们定义 samej,i0i<n)表示将第 j 列上移 i 个单位后,有几个数是不用变的。那么上移了 i 个单位以后,自然还有 nsamej,i 个数是需要变的,那么就要花费 nsamej,i 次修改操作,上移也花费了 i 次操作,那第 j 列的最优方案就是 min0i<n(i+nsamej,i),最终答案就是:

ans=j=1m(min0i<n(i+nsamej,i))

现在唯一的问题就是如何求出 same 了。我们发现,如果一个数 ai,j应该出现在第 j 的数字,那么一定有 jai,jn×m,同时 ai,jj(modm)(后者在代码里写作了  (a[i][j] - j) % m )。

如果上面的条件满足了,那我们就可以算一下 ai,j 这个数字应该出现在哪一行。显然,它应该出现在 ai,jjm+1 行(记作 k)。

那如果我们把 ai,j 移到第 k 行,它就不用变了。回顾 same 的定义,从第 i 行移到第 k 行,要移动几次呢?

  • 如果 ik,移动 ik 个单位即可;
  • 如果 i<k,那首先把它移到第 1 行需要 i1 次,然后再移 1 次到第 n 行,从第 n 行移到第 k 行需要 nk 次,加起来,就是 i1+1+nk,化简得 ik+n

如果合并的话,就是要移动 (ik+n)modn 次,那么我们就可以把 samej,(ik+n)modn 增加 1 了。

注意 n,m 都有可能达到 2×105,所以需要开不定长数组,时间复杂度 O(nm)same 可以每列重复使用,舍去前一个维度。

代码贴出,仅供参考。

posted @   syksykCCC  阅读(452)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示