Codeforces Round 1040 (Div. 2) A - D题详细题解

本文为Codeforces Round 1040 (Div. 2) A - D题的详细题解, 觉得有帮助或者写的不错可以点个赞!

目录

题目A:

题目大意:

解题思路:

代码(C++):

题目B:

题目大意:

解题思路:

代码(C++):

题目C:

题目大意:

解题思路:

代码(C++):

题目D:

题目大意:

解题思路:

代码(C++):


题目A:

Problem - A - Codeforces

题目大意:

现在定义,a是数组,sum(a)即为数组a中所有元素的和。

mex(a)即为数组a的最小排除数,也就是不在数组a中的最小非负整数

现在给出你一个数组S,并且刚开始你的得分为0。

每次操作你可以从数组中取出一个一部分元素(也就是原数组会少一部分元素),把这部分元素组成的数组设置成b。

你可以对你的分数加上sum(b)或者mex(b)。

在你进行任意次操作后,求出得分的最大值。

解题思路:

感性的分析,取出来的数字要使得mex值很大,那肯定要求很苛刻,要包含从0开始连续的数字才行。

理性的分析,

mex{0} > sum{0}

mex{0, 1} > sum{0, 1}

mex{0, 1,  2} == sum{0, 1, 2}

mex{0, 1, 2, 3} < sum(0, 1, 2, 3)

很容易分析出,接下来的mex都是小于sum的

也就是得出结论,数组中有0和1的时候,取出0,1,并且把分数加上mex。

其他时候再加上sum。

更深层次的思考,mex{1} < sum{1}, mex{0} > sum{0}。

那么得出最终结论:

我们把数组中的每一个0单独取出来,加上mex{0},也就是1,也就是0的个数。

然后把其他的数字取出来,直接加到分数上。

代码(C++):

void solve() {int n;std::cin >> n;int sum = 0, cnt0 = 0;for (int i = 0; i < n; i++) {int x;std::cin >> x;//求出这些数字的总和sum += x;//0可以单独拿出来作为一个集合{0},MEX{0} = 1//所以只需要求出1的数量即可if (x == 0) {cnt0++;}}std::cout << sum + cnt0 << "\n";
}

题目B:

Problem - B - Codeforces

题目大意:

现在给你一个数组,里面只包含元素0, 1, 2, 并且保证0,1,2的三个数字的数量至少为1。

现在玩家A,要从数组的第一个元素开始,走到最后一个元素,每次可以往左或者往右走一格。

每次经过的元素都会加在自己的得分上(每一个元素都可以重复的计算),玩家A的目标是在走到最后一个元素上并且加到那个元素的值后,得分恰好为S (不能超过也不能小于S)。

现在初始数组为a。

现在你是玩家B,你需要重新打乱数组,使得玩家A怎么都不能得到分数S。

输出打乱后的数组,如果玩家A怎么都能得到分数S,输出-1.

解题思路:

我们很容易注意到,玩家A直接从头走到尾,会加上数组a的所有元素,我们记作tot。

也就是说,玩家A能获得的分数最小值为tot,那么S < tot的时候,肯定是无法恰好获得S分的,此时怎么排列数组都可以。

当S == tot的时候,一遍走过去就恰好达到分数S了,此时无论怎么排列数组,都会产生S分。

当S > tot的时候,此时玩家A就可以通过”刷分“操作来获取更多的得分。

我们进行如下分析:

由于数组中只存在0, 1, 2。并且保证0,1,2的三个数字的数量至少为1。

当数组中有01相邻的时候,“左右横跳”,可以获得任意的得分。

从上面的结论可以知道,在S  > tot的前提下,如果数组中有0,1相邻,玩家A肯定能获得恰好S分。

当数组中有02相邻的时候,每次左右横跳,都会获得得分2。

当数组中有11相邻的时候,每次左右横跳,都会获得得分3。

当数组中有12相邻的时候,每次左右很跳,都会获得得分4。

根据上述分析,我们现在把0和1分开摆放,可以类似于:

{0, 0, ..., 0, 2, 2, ..., 2, 1, ... ,1},现在S > tot。

我们再进行如下的分析:

当S == tot + 1,玩家A无论怎么操作都得不到S。

当S == tot + 2,玩家A可以通过02横跳来得到。

当S == tot + 3,  11横跳。

当S == tot + 4,  21横跳。

...

也就是只有在S == tot + 1的时候,玩家A怎么操作都得不到S。

综合上述推理我们即可实现代码。

代码(C++):

void solve() {int n, s;std::cin >> n >> s;//分别计算出0,1,2的数量int cnt0 = 0, cnt1 = 0, cnt2 = 0;for (int i = 0; i < n; i++) {int x;std::cin >> x;if (x == 0) {cnt0++;} else if (x == 1) {cnt1++;} else {cnt2++;}}//根据数组中1,2的数量计算数组元素的总和int tot = cnt1 + cnt2 * 2;/*此部分分析看题解*/if (s < tot || s == tot + 1) {for (int i = 0; i < cnt0; i++) {std::cout << "0 ";}for (int i = 0; i < cnt2; i++) {std::cout << "2 ";}for (int i = 0; i < cnt1; i++) {std::cout << "1 ";}std::cout << "\n";} else {std::cout << "-1\n";}
}

题目C:

Problem - C - Codeforces

题目大意:

现在有m个数对(ai, bi),我们定义集合S = {(a1, b1), (a2, b2), (a3, b3), ...,(am, bm)}。

现在定义两个值f(S)和g(S)。

1.把每个数对中的(a,b)表示一个区间[a, b]。

f(S)为集合S所包含的所有区间的并集长度

2.现在(a, b)为图中的一条无向边。

g(S)是一个长度至少为3的环的节点数量。

现在给你n个数对(a, b),你需要从中取一部分数对组成集合S,你需要使得

f(S) - g(S)尽可能的大,输出此时你取的集合大小和集合里面包含的元素(原来数对的索引)。

解题思路:

感性的思考,定义t = f(S) - g(S),要使得t越来越大,那么我们需要使得f(S)越大,g(S)越小。

取更多的数对只会让f(S)越大,但是如果出现环的话,g(S)会瞬间增大很多。

也就是说,我们尽可能的取更多的数对,但是尽可能的不让g(S)出现环,此时能让t尽可能的最大。

理想分析:对于一些数对,[x1, x2], [x2, x3], [x3, x4]...[x(k - 1), x(k)],他们两两相连组成了一个环,也就是x1 == xk。

很容易知道这段区间的并集大小就是{x1, x2, ..., xk}中的最大值减去最小值, 因为两两相连,不用考虑空的部分。

我们如果删去其中的一个点[x1, x2],那么环就不存在了, 但是很容易发现并集大小是不变的。

所以,我们可以无脑的删除所有可以连成环的点,这样就可以保证最终的值是最大的!

可以用并查集快速判断是否成环。实际操作看具体代码

代码(C++):

//https://leetcode.cn/discuss/post/3583665/fen-xiang-gun-ti-dan-chang-yong-shu-ju-j-bvmv/
class UnionFind {std::vector<int> fa;std::vector<int> sz;
public:int cc;UnionFind(int n) : fa(n), sz(n, 1), cc(n) {std::iota(fa.begin(), fa.end(), 0);}int find(int x) {if (fa[x] != x) {fa[x] = find(fa[x]);}return fa[x];}bool is_same(int x, int y) {return find(x) == find(y);}bool merge(int from, int to) {int x = find(from), y = find(to);if (x == y) {return false;}fa[x] = y;sz[y] += sz[x];cc--;return true;}int get_size(int x) {return sz[find(x)];}
};void solve() {int n;std::cin >> n;std::vector<std::pair<int, int>> a(n);for (int i = 0; i < n; i++) {std::cin >> a[i].first >> a[i].second;}int mx = 2 * n;UnionFind uf(mx + 1);std::vector<int> ans;for (int i = 0; i < n; i++) {int u = a[i].first;int v = a[i].second;if (uf.merge(u, v)) {ans.push_back(i + 1);}}std::cout << ans.size() << "\n";for (int x : ans) {std::cout << x << " ";}std::cout << "\n";
}

题目D:

Problem - D - Codeforces

题目大意:

现在有一个长度为n的排列P。

你需要构造一个长度为n的数组a,对于每一个ai,

你可以选择ai = pi 或者 ai = 2 * n - pi。

你的目的是使得数组a中的逆序对数目最少,输出这个最小数目。

解题思路:施工中

代码(C++):

//https://leetcode.cn/discuss/post/3583665/fen-xiang-gun-ti-dan-chang-yong-shu-ju-j-bvmv/
template<typename T>
class FenwickTree {std::vector<T> tree;public:FenwickTree(int n) : tree(n + 1, 0) {}void update(int i, T val) {for (; i < tree.size(); i += i & -i) {tree[i] += val;}}T pre(int i) const {T res = 0;for (; i > 0; i &= i - 1) {res += tree[i];}return res;}T query(int l, int r) const {if (r < l) {return 0;}return pre(r) - pre(l - 1);}T total(int n) const {return pre(n);}
};void solve() {int n;std::cin >> n;std::vector<int> p(n + 1);for (int i = 1; i <= n; i++) {std::cin >> p[i];}std::vector<int> l(n + 1), r(n + 1);FenwickTree<int> bit(n);i64 base = 0;for (int i = 1; i <= n; i++) {int x = i - 1 - bit.pre(p[i]);l[i] = x;base += x;bit.update(p[i], 1);}bit = FenwickTree<int> (n);for (int i = n; i >= 1; i--) {int x = bit.total(n) - bit.pre(p[i]);r[i] = x;bit.update(p[i], 1);}i64 ans = base;for (int i = 1; i <= n; ++i) {int x = r[i] - l[i];if (x < 0) {ans += x;}}std::cout << ans << '\n';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91511.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 之 【排序】(计数排序)

目录 1.计数排序的思想 2.计数排序图解 3.计数排序代码逻辑 3.1求原数组最大最小值及计数数组的创建 3.2计数 3.3覆盖写 3.4释放资源 4.计数排序的注意事项 5.计数排序的时间复杂度与空间复杂度 以升序为例 1.计数排序的思想 前面我们学习的快排、归并排序、希尔排序.…

Ascend CANN/ACL API 模型部署加速最佳实践

1. 模型输入相关问题 图像尺寸信息 模型输入尺寸由原始模型决定,在转换时固定 图像尺寸信息是模型固有属性,不是转换时添加的 对于使用动态尺寸,可以在推理时自动根据当前的输入尺寸推导输出尺寸。 输入格式(NCHW/NHWC) --input_format 不同框架默认格式不同: Caffe: 支持…

QT信号和槽怎么传输自己定义的数据结构

在 Qt 中&#xff0c;信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;机制默认支持许多内置类型&#xff08;如 int、QString、QList 等&#xff09;&#xff0c;但如果要传输 自定义数据结构&#xff08;如结构体、类对象&#xff09;&#xff0c;需要额…

借助于llm将pdf转化为md文本

pdf转化为md格式后&#xff0c;意味着非结构化文本转为结构化文本&#xff0c;能清晰定位大标题、子标题&#xff0c;图表。 方便后续处理&#xff0c;因为llamaindex和langchain能更有效切分md类文本&#xff0c;避免信息丢失。 1&#xff09;读取pdf为txt 读取pdf&#xf…

设计模式:中介者模式 Mediator

目录前言问题解决方案结构代码前言 中介者是一种行为设计模式&#xff0c;能让你减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交互&#xff0c;迫使它们通过一个中介者对象进行合作。 问题 假如你有一个创建和修改客户资料的对话框&#xff0c; 它由各种控件…

计算机基础速通--数据结构·线性表应用

如有问题大概率是我的理解比较片面&#xff0c;欢迎评论区或者私信指正。 考察线性表&#xff0c;核心围绕其存储结构特性、核心操作实现、场景应用选型三大维度&#xff0c;重点检验对基础概念的理解、代码实现能力及问题分析能力&#xff0c;通常会结合算法设计、复杂度分析和…

LeetCode Hot 100:42. 接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 解析 和题目 盛水最多的容器 类似&#xff0c; LeetCode Hot 100&#xff1a;11. 盛最多水的容器-CSDN博客 只是这里将每一个柱子视为一个宽度为…

【C语言入门级教学】字符指针变量

文章目录1.字符指针变量2. 数组指针变量2.1 数组指针变量初始化3.⼆维数组传参的本质1.字符指针变量 在指针的类型中我们知道有⼀种指针类型为字符指针 char* ; ⼀般使⽤: int main() { char ch w; char* pc &ch;//pc的类型是char**pcw;//对pc解引用 修改ch存放的内容…

【Shell脚本自动化编写——报警邮件,检查磁盘,web服务检测】

Shell脚本自动化编写Shell脚本自动化编写一、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。第一步&#xff1a;准备工作第二步&#xff1a;配置邮件信息第三步&#xff1a;检查磁盘的自动…

Java 接口(下)

三、接口的继承性【基础重点】 1. Java中的接口之间的继承关系是多继承&#xff0c;一个接口可以有多个父接口(1) 语法&#xff1a;interface 接口名 extends 父接口1,父接口2{} 2. 类和接口之间是多实现的关系&#xff1a;一个类可以同时实现多个接口(1) 语法&#xff1a;clas…

学习游戏制作记录(各种水晶能力以及多晶体)8.1

1.实现创建水晶并且能与水晶进行交换位置的能力创建好水晶的预制体&#xff0c;添加动画控制器&#xff0c;传入待机和爆炸的动画创建Crystal_Skill_Control脚本&#xff1a;挂载在水晶预制体上private float crystalExstTime;//水晶存在时间public void SetupCrystal(float _c…

在vscode 如何运行a.nut 程序(Squirrel语言)

在 VS Code 中运行 Squirrel 语言编写的 .nut 程序&#xff0c;需要先配置 Squirrel 运行环境并安装相关插件&#xff0c;具体步骤如下&#xff1a; 一、安装 Squirrel 解释器 Squirrel 程序需要通过其官方解释器 squirrel 或 sq 执行&#xff0c;首先需要安装解释器&#xf…

【数据结构】生活中的数据结构:从吃饭与编程看栈与队列思维

生活中的数据结构&#xff1a;从吃饭与编程看栈与队列思维 在软件开发的世界里&#xff0c;栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;是两种基础的数据结构&#xff0c;它们以不同的顺序管理数据&#xff1a;栈遵循后进先出&#xff08;LIFO&#x…

牛客——接头密匙

题目链接&#xff1a;牛客--接头密匙 该题是一个很显然的前缀树问题&#xff0c;只需要构建a中所有数组对应的前缀树&#xff0c;之后求b所处前缀个数即可。关于前缀树的构建&#xff0c;可以观看左老师算法讲解045的视频&#xff0c;简单来讲就是用特殊字符将实际数据隔开&…

【Linux基础知识系列】第六十三篇 - 文件编辑器基础:vim

在 Linux 系统中&#xff0c;文本编辑器是系统管理员和开发人员不可或缺的工具。vim 是一个功能强大的文本编辑器&#xff0c;广泛应用于 Linux 系统中。它支持多种编辑模式&#xff0c;提供了丰富的文本编辑功能&#xff0c;适用于编写代码、配置文件和文档。掌握 vim 的基本使…

音频驱动的视觉特效:粒子、动画与Shader的融合技术

音频驱动视觉效果的实现与应用1. 引言在互动媒体、游戏和数字艺术领域&#xff0c;音频数据实时控制视觉元素已成为核心技术&#xff0c;它能创造沉浸式体验&#xff0c;增强用户参与感。例如&#xff0c;音乐会可视化或VR游戏中&#xff0c;音频信号驱动粒子流动、动画变化和S…

机器学习环境配置

【终极指南】吃透机器学习环境配置&#xff1a;从Conda、CUDA到Docker容器化 大家好&#xff01;在机器学习的旅程中&#xff0c;一个稳定、可复现的环境是成功的基石。 第一部分&#xff1a;核心理念——为何环境配置如此重要&#xff1f; 任何机器学习模型的运行&#xff0c;…

【14】大恒相机SDK C#开发 ——Bitmap.UnlockBits()什么意思?有什么用?bmpData.Scan0;什么意思?有什么用?

文章目录1 Bitmap.UnlockBits()2 bmpData.Scan01 Bitmap.UnlockBits() 在 C# 中&#xff0c;Bitmap.UnlockBits() 方法的作用是解锁通过 Bitmap.LockBits() 方法锁定的位图数据&#xff0c;并释放相关的位图数据结构。 当你使用 Bitmap.LockBits() 方法锁定位图数据时&#x…

什么是doris

文章目录简介使用场景Apache Doris 主要应用于以下场景&#xff1a;实时数据分析&#xff1a;湖仓融合分析&#xff1a;半结构化数据分析&#xff1a;Apache Doris 的核心特性详细请看官方文档&#xff1a; Apache Doris介绍简介 Apache Doris 是一款基于 MPP 架构的高性能、实…

python+pyside6的简易画板

十分简单的一个画板程序&#xff0c;用QLabel控件作为画布&#xff0c;在画布上可以画出直线、矩形、填充矩形、园&#xff0c;椭园、随手画、文本等内容。将原先发布的画板程序中的画文本方法修改成了原位创建一编辑框&#xff0c;编辑框失去焦点后&#xff0c;即将文本画在画…