Before the Beginniing

本文为 Clouder 原创文章,原文链接为Click,转载时请将本段放在文章开头显眼处。如进行了二次创作,请明确标明。

由本人转载于博客园。

题意分析

Codeforces题目链接

给出一个 \(n \times m\) 的矩阵,给出两种操作:

  1. 将某一列整体向上移动一位。
  2. 修改某一个位置的值。

求最少要多少次操作,使得矩阵成为如下形式:

思路

很容易发现,每一列的操作都是独立的。

那么就一列列处理即可。

问题转化为如何求一列变为目标形式的最少操作次数。

而修改和平移是不冲突的,可以直接考虑先平移再修改。

暴力枚举法

于是得到一个很直观的思路,枚举向上移动多少次,再检查每一个数计算要修改多少次达到目标状态。

这样每列的复杂度是 \(O(n^2)\) 的,总复杂度显然不可接受。

计算位置法

考虑每列要修改多少次受什么影响。

在向上平移特定距离之后,如果平移后有位置刚好对应上,则不需要修改。

每个位置数确定之后,其能对应的位置也确定了,可以直接计算出在平移几格时的情况该位置不需要修改。

比如图中第一列,第二行如果有一个数 \(1\),可以直接通过计算得出其应当在的位置为第一行,于是在平移一格时的情况它不用修改,记录下来即可。

那么整体把矩阵扫一遍处理即可,时间复杂度 \(O(nm)\),可以通过。

解法

还是有一些细节的。

首先不能直接开 \(nm\) 大小的数组,会爆空间,这里使用了 vector 来处理。

而 \(s[i]\) 代表的是 向上平移 \(i\) 格时有多少个位置不需要修改。

那么操作步数可以通过平移格数和修改数计算出。

这里的数组 \(s\) 直接滚动优化掉一维,注意使用循环清空,就不会清空不使用的部分,而用 memset 会超时。

计算新位置建议自己画图手推一下,代个例子进去。

由于使用 vector,下标从 \(0\) 开始了,按个人习惯来吧。

代码

  1. #include <cstdio>
  2. #include <vector>
  3. using namespace std;
  4. inline int read()
  5. {
  6. static char c;
  7. int r = 0;
  8. for (c = getchar(); c > '9' || c < '0'; c = getchar());
  9. for (; c >= '0' && c <= '9'; r = (r << 1) + (r << 3) + (c ^ 48), c = getchar());
  10. return r;
  11. }
  12. const int maxn = 2e5 + 100;
  13. int n, m;
  14. vector<int> a[maxn];
  15. int s[maxn];
  16. int ans;
  17. int main()
  18. {
  19. n = read();
  20. m = read();
  21. for (int i = 0; i < n; ++i)
  22. for (int j = 0; j < m; ++j)
  23. a[i].push_back(read());
  24. int maxx = n * m;
  25. for (int j = 0; j < m; ++j)
  26. {
  27. for (int i = 0; i < n; ++i)
  28. s[i] = 0;
  29. for (int i = 0; i < n; ++i)
  30. {
  31. if (a[i][j] > maxx || a[i][j] < j || ((a[i][j] - j - 1) % m) != 0)
  32. continue;
  33. int p = (a[i][j] - j - 1) / m;
  34. if (i >= p)
  35. s[i - p]++;
  36. else
  37. s[i + n - p]++;
  38. }
  39. int res = 1 << 30;
  40. for (int i = 0; i < n; ++i)
  41. if (n - s[i] + i < res)
  42. res = n - s[i] + i;
  43. ans += res;
  44. }
  45. printf("%d\n", ans);
  46. return 0;
  47. }

[Codeforces #615 div3]1294E Obtain a Permutation的更多相关文章

  1. Codeforces 1294E - Obtain a Permutation

    题目大意: 给定一个n*m的矩阵 可以更改任意一个位置的值 也可以选择一整列全部往上移动一位,最上方的数移动到最下方 问最少操作多少次可以把这个矩阵移动成 1 2 3 ... m m+1 m+2 m+ ...

  2. Codeforces #550 (Div3) - G.Two Merged Sequences(dp / 贪心)

    Problem  Codeforces #550 (Div3) - G.Two Merged Sequences Time Limit: 2000 mSec Problem Description T ...

  3. Codeforces 1091D New Year and the Permutation Concatenation 找规律,数学 B

    Codeforces 1091D New Year and the Permutation Concatenation https://codeforces.com/contest/1091/prob ...

  4. codeforces 615 D. Multipliers (数论 + 小费马定理 + 素数)

    题目链接: codeforces 615 D. Multipliers 题目描述: 给出n个素数,这n个素数的乘积等于s,问p的所有因子相乘等于多少? 解题思路: 需要求出每一个素数的贡献值,设定在这 ...

  5. codeforces 615 B. Longtail Hedgehog (DFS + 剪枝)

    题目链接: codeforces 615 B. Longtail Hedgehog (DFS + 剪枝) 题目描述: 给定n个点m条无向边的图,设一条节点递增的链末尾节点为u,链上点的个数为P,则该链 ...

  6. codeforces #579(div3)

    codeforces #579(div3) A. Circle of Students 题意: 给定一个n个学生的编号,学生编号1~n,如果他们能够在不改变顺序的情况下按编号(无论是正序还是逆序,但不 ...

  7. U - Obtain a Permutation CodeForces - 1294E 思维

    题解: 注意每一列与每一列之间互不影响,所以贪心地求出没一列的最小操作值,然后累加起来. 怎么求没一列的最小值呢?维护一个数组same表示其中same[i]=j表示将该序列向上翻滚i次有j个元素归位, ...

  8. Twist the Permutation 数列的轮换题 Codeforces 776 div3

    这是一道比较经典的将数列中的数字轮换的题目,我们先看题干: 题干分析:先浅浅地分析一下题目是要我们干什么,我们会默认有一个已经升序排序地1~n的排列,然后我们会给定一个新排列是在原有排列的基础上进行o ...

  9. Educational Codeforces Round 7 D. Optimal Number Permutation 构造题

    D. Optimal Number Permutation 题目连接: http://www.codeforces.com/contest/622/problem/D Description You ...

随机推荐

  1. PAT T1025 Keep at Most 100 Characters

    删除字符的镜像问题,状态转移方程一样~ #include<bits/stdc++.h> using namespace std; ; ; string s; long long dp[ma ...

  2. Spring Boot 学习方法论-如何正确的入门 Spring Boot

    想要入门 Spring Boot,那么什么样的教程是符合初学者学习的(没有太多的Java基础但有一些程序基础或者软件编程知识). 这恰好能够勾出很多问题,比如是文章图文教程适合还是视频教程适合零基础初 ...

  3. 学习笔记(7)- 基于LSTM的对话模型

    LSTM based Conversation Models 本文介绍一种会话语言模型,结合了局部.全局的上下文,以及参与者的角色. 问题提出者 倾向于用"任何人"."如 ...

  4. vue.js 第十课-第十六课

    第十课: http://note.youdao.com/noteshare?id=25b5ba45286464856f21eb4b6b391ecd&sub=19C4429995384F72BD ...

  5. 3、gitlab备份与恢复

    1.备份 #修改配置文件,启用备份 [root@localhost ~]# vim /etc/gitlab/gitlab.rb 377 gitlab_rails['backup_path'] = &q ...

  6. php 微信小程序支付

    php 微信小程序支付 直接贴代码: 前端测试按钮wxml: <view class="container"> <text class="name&qu ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:缩写

    <!DOCTYPE html> <html> <head> <title>Bootstrap 实例 - 缩写</title> <lin ...

  8. 820算法复试 Eratasthene 质数筛选

    Eratasthene 学问之道无他,求其放心而巳矣 https://blog.csdn.net/qq_37653144/article/details/80470029 class Solution ...

  9. HDU 5564:Clarke and digits 收获颇多的矩阵快速幂 + 前缀和

    Clarke and digits  Accepts: 16  Submissions: 29  Time Limit: 5000/3000 MS (Java/Others)  Memory Limi ...

  10. C++获取驱动盘句柄

    转载:https://www.cnblogs.com/sherlock-merlin/p/10792116.html     https://univasity.iteye.com/blog/8052 ...