Codeforces Round #842 (Div. 2) A-D题解

比赛链接

A、Greatest Convex

非常的简单。根据样例直接猜是输出 n1.

上一个 Python 代码。

T = int(input()) while T > 0: T -= 1 n = int(input()) print(n - 1)

B、Quick Sort

题目大意是每次选 k 个,然后把他们排序后放到末尾。
那不妨这么看。每次我们先把已经有序的部分提取出来,即 1,2,3... 一直到最后一位。对于这些已经有序的部分,我们是不用进行任何操作的。而对于他们周围以及中间的无序部分,我们全部都要提取出来并排序。(无序部分的排序规则很简单,每次选未被排序的前 k 小并将其排到末尾。)那么,如果碰到不是 k 的倍数怎么办?可以发现,将已经有序的最后几位扒出来跟多余部分再排就好了。 所以答案就是无序部分的个数 num/k(向上取整)。

#include <bits/stdc++.h> using namespace std; #define N 1000100 int n, k; int a[N]; int main(){ int T; cin >> T; while(T--){ cin >> n >> k; for(int i = 1; i <= n; i++) cin >> a[i]; int now = 1, tot = 0; for(int i = 1; i <= n; i++){ if(a[i] == now){ now++; tot++; } } int sum = n - tot; int ans = sum / k + (sum % k != 0); cout << ans << endl; } return 0; }

C、Elemental Decompress

首先特判几个显然的特殊情况:

  1. 任何数字出现个数不超过 3
  2. 最大值必须出现(不能为 0 次)
  3. 最小值(即 1) 出现次数不超过 1 次。

然后考虑普通数字的出现 0,1,2次 情况。
对于出现一次的数字,有个显然的方法,就是两个数组都放同样的数字(自己)。可以发现这样放比起其中一个放更小的值是绝对不亏的。(不可能放更大的值对吧。)
对于出现两次的数字,我们记录下来他们出现的两个位置。然后两个数组分别设为对应值即可。
可以发现,如果有出现两次的数字,那么两个数组对应的另外一个位置就会出现空缺。那么我们肯定要在对应的那个空缺填上一个更小值。可以发现,这时候我们剩下的能填的值只有出现 0 次的数字。最优填法肯定就是每次填一个最大的小于他的数。所以把所有剩下的数字放进 set 里面,用lower_bound 查询一下是否等于begin(),如果不是,就 it--, 取得对应值。如果是,就说明没有更小值,输出 NO 即可。

#include <bits/stdc++.h> using namespace std; #define N 200010 int n, k; int a[N]; int vis[N]; // 每个数字的出现次数 int ans[N][2]; vector <int> G[N]; // 每个数字出现的位置 int main(){ // freopen("hh.txt", "r", stdin); int T; cin >> T; while(T--){ for(int i = 1; i <= n; i++){ ans[i][0] = ans[i][1] = 0; G[i].clear(); } int maxn = 0; cin >> n; for(int i = 1; i <= n; i++) cin >> a[i], maxn = max(maxn, a[i]); for(int i = 1; i <= maxn; i++) vis[i] = 0; for(int i = 1; i <= n; i++){ G[a[i]].push_back(i); } set <int> s; bool flag = 1; for(int i = 1; i <= maxn; i++){ sort(G[i].begin(), G[i].end()); if(G[i].size() == 0) s.insert(i); else if(G[i].size() == 1) ans[G[i][0]][0] = ans[G[i][0]][1] = i; else if(G[i].size() == 2){ ans[G[i][0]][0] = ans[G[i][1]][1] = i; } else if(G[i].size() >= 3){ flag = 0; break; } } if(G[n].size() == 0) flag = 0; if(G[1].size() > 1) flag = 0; for(int i = 1; i <= n; i++){ if(ans[i][0] && !ans[i][1]){ int pos = G[ans[i][0]][1]; // 二号位的 pos set<int>::iterator it = s.lower_bound(ans[i][0]); if(it == s.begin()){ flag = 0; break; } else{ it--; ans[i][1] = ans[pos][0] = *it; s.erase(it); } } } if(!flag){ puts("NO"); } else{ puts("YES"); for(int i = 1; i <= n; i++) printf("%d ", ans[i][0]); cout << endl; for(int i = 1; i <= n; i++) printf("%d ", ans[i][1]); cout << endl; } } return 0; }

D、Lucky Permutation

发现题目要求只剩下一个逆序对。
可以想到,这个剩下的逆序对肯定是原序列(称有序序列为原序列)中相邻的两个数。那么不妨先把他们排成总体有序的数列,这样子就和题目要求的情况只有一步之遥了。
考虑如何求出排成总体有序数列的最快步数。

偷懒,上 Tutorial 截图先。
666
这句话是什么意思呢,就是将序列按照下标的下标,下标的下标的下标。。。。。建成一张图。可以发现这张图就是一个个环。注意,这里是通过下标的访问建图的。而下标也就对应着这个数字本应前往的地方。因此,如果我们要进行排序,对于一个环上所有的数字,只需要在环内进行交换即可。那么,对于一个有 k 个元素的环,我们不妨以其中一个点为基准,将他沿任意固定方向一直移动(交换),那么我们只需要移动 k1 次便能使环上元素全部到达其应到的位置。

接下来考虑如何剩下一个逆序对。其实这个过程就是在对原序列排成整体有序时,某一对相邻元素不交换。因此,如果有任意一对相邻元素在同一个环内,我们就可以将两个元素反向移动,只需要 k2 步便能达到对方的应到位置,形成逆序对,故此时总答案减一。
如果没有任何一组,那么我们只能在完全排有序后将任意一组互换,故此时总答案加一。

上一个 C# 代码。

using System; namespace CodeForces { class NewBaseType { public static void Main(string[] args) { var T = Convert.ToInt32(Console.ReadLine()); while(T > 0){ T--; var n = Convert.ToInt32(Console.ReadLine()); int[] a = new int[n + 10]; string[] tmp = Console.ReadLine().Split(); for(int i = 0; i < tmp.Count(); i++){ a[i] = Convert.ToInt32(tmp[i]) - 1; } int[] comp = new int[n + 10]; int id = 1, ans = 0; for(int i = 0; i < n; i++){ if(comp[i] != 0) continue; int v = i; while(comp[v] == 0){ comp[v] = id; v = a[v]; ans++; } id++; ans--; } bool flag = false; for(int i = 0; i < n - 1; i++){ if(comp[i] == comp[i + 1]){ flag = true; break; } } if(flag == true){ Console.WriteLine(ans - 1); } else Console.WriteLine(ans + 1); } } } }
文章来源: https://www.cnblogs.com/wondering-world/p/17030453.html
All rights reserved ©雪之下,树之旁

__EOF__

本文作者雪之下,树之旁
本文链接https://www.cnblogs.com/wondering-world/p/17030453.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   雪之下,树之旁  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示