比赛链接:Dashboard - Codeforces Round #792 (Div. 1 + Div. 2) - Codeforces

C. Column Swapping

题意:

给定一个n*m大小的二维数组,要求只进行一次两列交换,使得得到的新数组的每行都是不减的。特别的,允许交换的两列是相同列。

思路:构造

可以考虑复制一份数组,并将其排序,那么两个数组中出现数字大小不同的列就是需要进行交换的列。

设需要交换的列的数量为num:

◇ 当num=0,无需交换,可以直接选择交换1 1。
◇ 当num=2时,尝试交换两列,并判断交换后,每行的这两列位置的数字是否已与排序后的该位置的数字相等。
◇ 当num>2时,那么需要交换的次数是大于1的,故无法满足要求。

参考代码:

  1. #include <bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4.  
  5. const int N = 200010;
  6.  
  7. int n, m;
  8. vector<int> v[N], nv[N];
  9.  
  10. bool check(int c1, int c2)
  11. {
  12. for(int i = 0; i < n; i++)
  13. if(v[i][c1] != nv[i][c2] || v[i][c2] != nv[i][c1]) return false;
  14. return true;
  15. }
  16.  
  17. void solve()
  18. {
  19. cin >> n >> m;
  20. for(int i = 0; i < n; i++) v[i].clear();
  21.  
  22. for(int i = 0; i < n; i++) {
  23. for(int j = 0; j < m; j++) {
  24. int x;
  25. scanf("%d", &x);
  26. v[i].push_back(x);
  27. }
  28. nv[i] = v[i];
  29. sort(nv[i].begin(), nv[i].end());
  30. }
  31.  
  32. int pos1 = -1, pos2 = -1;
  33. bool ok = true;
  34. for(int i = 0; i < n; i++) {
  35. for(int j = 0; j < m; j++) {
  36. if(v[i][j] != nv[i][j]) {
  37. if(pos1 == -1 || pos1 == j) pos1 = j;
  38. else if(pos2 == -1 || pos2 == j) pos2 = j;
  39. else ok = false;
  40. }
  41. }
  42. }
  43.  
  44. if(!ok) puts("-1");
  45. else {
  46. if(pos1 == -1 && pos2 == -1) puts("1 1");
  47. else if(check(pos1, pos2)) printf("%d %d\n", pos1 + 1, pos2 + 1);
  48. else puts("-1");
  49. }
  50. }
  51.  
  52. int main()
  53. {
  54. int test;
  55. cin >> test;
  56. while(test--) solve();
  57.  
  58. return 0;
  59. }

D. Traps

题意:

给定一个大小为n的数组a[]为基础花费,以及最大跳过次数k:每次跳过可直接越过一格,但同时,后续走的每一格都增加1的附加花费。当从 i-1 走到 i 且已进行 cnt 次跳过操作时,此次花费为ai + cnt。求从0走到n所需的最小花费。

思路:贪心 构造

取 ai + i 最大的 min(n, k) 个格子跳过,然后模拟一下求总花费即可。

证明:

☆ 跳过次数应为min(n,k):

  假设当前跳过次数为K,且仍有可跳过的格子且还有跳过次数,那么考虑跳过最后一个未跳过的格子,最终的花费必定只减不增。因此,跳过次数越多,结果越优。

☆ 取 ai + i 较大的格子跳过:

  假设有ax + x > ay + y,若只跳过x和y其中某一格,有两种情况,其中二者出现差异的部分仅在区间 [x,y]内,若假设此前跳过了cnt步,则有:

  ① 跳过x:cost1 = sum[x + 1,y] + (cnt + 1) * (y - x).

  ② 跳过y:cost2 = sum[x,y - 1] + cnt * (y - x).

  进而,cost1 - cost2 = ay - ax + y - x = ay + y - (ax + x) < 0 ,即跳过x的花费比跳过y更小。

  因此,应考虑优先跳过 ai + i 较大的格子。

参考代码:

  1. #include <bits/stdc++.h>
  2. #define LL long long
  3. #define PII pair<int,int>
  4. using namespace std;
  5.  
  6. const int N = 200010;
  7.  
  8. int n, k, a[N], id[N];
  9. PII p[N];
  10.  
  11. void solve()
  12. {
  13. cin >> n >> k;
  14. for(int i = 1; i <= n; i++) {
  15. scanf("%d", &a[i]);
  16. p[i] = { a[i] + i, i };
  17. }
  18. sort(p + 1, p + 1 + n, greater<PII>());
  19. for(int i = 1; i <= n && i <= k; i++) id[i] = p[i].second;
  20. sort(id + 1, id + 1 + min(n, k));
  21.  
  22. int cnt = 0;
  23. LL res = 0;
  24. for(int i = 1; i <= n; i++) {
  25. if(cnt < k && i == id[cnt + 1]) ++ cnt;
  26. else res += a[i] + cnt;
  27. }
  28. cout << res << endl;
  29. }
  30.  
  31. int main()
  32. {
  33. int test;
  34. cin >> test;
  35. while(test--) solve();
  36.  
  37. return 0;
  38. }

E. MEX vs DIFF

题意:

给一个大小为n的非负数组a,以及k次操作,每次操作可以将a中任意一个数变成任意数。

有mex为不包含与a中的最小的非负整数,dif为a中不同数的数量,求dif - mex的最小值。

思路:贪心 构造

可以发现dif必然不小于mex,dif - mex的值实际上等于:大于mex的不同数的个数。所以最终答案应该令mex尽量大,同时,让大于mex的不同数的个数尽量小。

令mex尽量大:先求mex的最大值。

令大于mex的不同数的个数尽量小:muitiset维护一下,让大于mex的数中,数量较少的数优先进行改变操作。

参考代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N = 100010;
  5.  
  6. int n, k, a[N];
  7. map<int,int> num, dnum;
  8.  
  9. void solve()
  10. {
  11. num.clear();
  12. cin >> n >> k;
  13. for(int i = 1; i <= n; i++) scanf("%d", &a[i]), ++ num[a[i]];
  14. dnum = num;
  15.  
  16. // 求mex最大值
  17. sort(a + 1, a + 1 + n);
  18. int mex = 0;
  19. while(num[mex]) ++ mex;
  20. for(int i = n, j = k; i && j; i--, j--) {
  21. if(a[i] < mex) break;
  22. num[mex] = 1, -- num[a[i]];
  23. while(num[mex]) ++ mex;
  24. }
  25.  
  26. // 求mex最大时,dif最小值
  27. multiset<int> S;
  28. for(auto i : dnum) {
  29. if(i.first > mex) S.insert(i.second);
  30. }
  31. int dif = mex;
  32. for(auto i : S) {
  33. if(k >= i) k -= i;
  34. else ++ dif;
  35. }
  36.  
  37. cout << dif - mex << endl;
  38. }
  39.  
  40. int main()
  41. {
  42. int test;
  43. cin >> test;
  44. while(test--) solve();
  45.  
  46. return 0;
  47. }

Codeforces Round #792 (Div. 1 + Div. 2) // C ~ E的更多相关文章

  1. Codeforces Round #792 (Div. 1 + Div. 2) A-E

    Codeforces Round #792 (Div. 1 + Div. 2) A-E A 题目 https://codeforces.com/contest/1684/problem/A 题解 思路 ...

  2. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  3. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  4. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  5. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  6. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  7. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  8. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  9. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

随机推荐

  1. 一文搞懂 Linux 的 inode!

    一个执着于技术的公众号 1.inode 是什么 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于 ...

  2. 推荐 | Linux 思维导图整理(建议收藏)

    一个执着于技术的公众号 作者:小柑 来源:https://www.jianshu.com/p/59f759207862 今天整理了一下收集的 Linux 思维导图.上传的均为高清原图,双击即可查看,也 ...

  3. IDEA通用配置

    文件的自动author注释

  4. CSAPP 之 CacheLab 详解

    前言 本篇博客将会介绍 CSAPP 之 CacheLab 的解题过程,分为 Part A 和 Part B 两个部分,其中 Part A 要求使用代码模拟一个高速缓存存储器,Part B 要求优化矩阵 ...

  5. 821. Shortest Distance to a Character - LeetCode

    Question 821. Shortest Distance to a Character Solution 思路:遍历字符串S,遇到与字符C相等就分别向左/右计算其他字符与该字符的距离,如果其他字 ...

  6. awd平台搭建及遇到的问题

    1.安装docker环境 a.使用的是ubuntu系统,通过sudo apt install docker.io进行docker得安装,此方式会自动启动docker服务. b.通过curl -s ht ...

  7. 【Unity Shader学习笔记】Unity基础纹理-渐变纹理

    纹理可以用来存储任何表面属性. 可以通过使用渐变纹理来实现插画风格的渲染效果. 这项技术是由Valve公司提出的.Valve使用它来渲染游戏中具有插画风格的角色. 我们使用半兰伯特模型计算漫反射. 因 ...

  8. 【算法】Floyd算法

    什么是Floyd Floyd用于求最短路程.举个栗子,给你一张图,让你求出点[1]到点[5]的最短路程,你会怎么求? (画图工具:CS Academy) 如上图,有向边分别是 1->2  1-& ...

  9. Linux下删除Mysql

    1.检查mysql服务并关闭相应的进程 [root@bp18425116f0cojd1vnz ~]# ps -ef |grep mysql root 1492 1 0 10:23 ? 00:00:00 ...

  10. DYOJ 【20220303模拟赛】最少分组 题解

    最少分组 题意 \(n\) 个点 \(m\) 条边的无向图,可以删掉 0 条或多条边,求满足条件的最小连通块数量: 对每个顶点对 \((a,b)\) ,若 \(a\) 和 \(b\) 同属于一个连通块 ...