牛客周赛 Round 60(下)
构造序列
题目描述
登录—专业IT笔试面试备考平台_牛客网
运行代码
#include <iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int main() {int n, m;cin >> n >> m;int minVal = min(n, m);int maxVal = max(n, m);cout << (n == m? 2 * minVal : 2 * minVal + 1);return 0;
}
代码思路
一、整体思路
- 首先从用户输入中读取两个整数
n
和m
,分别代表正数的数量和负数的数量。 - 然后使用
std::min
和std::max
函数求出n
和m
中的较小值minVal
和较大值maxVal
。 - 根据
n
和m
的关系计算最长序列的长度并输出。如果n
和m
相等,则最长序列长度为2 * minVal
;如果n
和m
不相等,则最长序列长度为2 * minVal + 1
。
二、原理分析
-
确定最小和最大数量:通过求出
n
和m
的最小值和最大值,可以方便地处理不同情况下的序列长度计算。如果n
和m
相等,那么最小数量和最大数量都是同一个值;如果n
和m
不相等,那么可以明确区分出较多的数和较少的数。 -
计算最长序列长度:当
n
和m
相等时,正好可以完全交替排列正数和负数,每一对正数和负数组成长度为 2 的子序列,所以最长序列长度为2 * minVal
。当n
和m
不相等时,以n > m
为例,先交替排列m
个正数和m
个负数,此时长度为2 * m
。然后还剩下n - m
个正数,由于正数不能相邻,所以只能在最后再添加一个正数,这样最长序列长度就是2 * m + 1
,即2 * minVal + 1
。同理m > n
时也一样。
连点成线
题目描述
登录—专业IT笔试面试备考平台_牛客网
运行代码
#include <iostream>
#include <climits>int main() {int n, m;std::cin >> n >> m;int xmax[n + 1] = {0};int xmin[n + 1];int ymax[n + 1] = {0};int ymin[n + 1];for (int i = 1; i <= n; ++i) {xmin[i] = INT_MAX;ymin[i] = INT_MAX;}int res = 0;for (int i = 0; i < m; ++i) {int x, y;std::cin >> x >> y;xmax[x] = std::max(xmax[x], y);xmin[x] = std::min(xmin[x], y);ymax[y] = std::max(ymax[y], x);ymin[y] = std::min(ymin[y], x);}for (int i = 1; i <= n; ++i) {res = std::max(res, std::max(xmax[i] - xmin[i], ymax[i] - ymin[i]));}std::cout << res;return 0;
}
代码思路
一、整体思路
- 首先读取棋盘大小
n
和棋子数量m
。 - 初始化用于记录每行和每列最大和最小坐标值的数组。对于每一行,初始时将最小坐标值设为极大值
INT_MAX
;对于每一列同理。 - 遍历
m
个棋子的坐标,对于每个棋子的坐标(x, y)
:更新x
行对应的最大纵坐标xmax[x]
和最小纵坐标xmin[x]
。更新y
列对应的最大横坐标ymax[y]
和最小横坐标ymin[y]
。 - 再次遍历从
1
到n
的行和列索引:计算每行的最大长度为xmax[i] - xmin[i]
,每列的最大长度为ymax[i] - ymin[i]
,取其中的较大值。将这个较大值与当前最长连线长度res
比较,取较大者更新res
。 - 最后输出最长连线的长度
res
。
二、原理分析
-
数据结构的选择:使用数组
xmax[n + 1]
、xmin[n + 1]
、ymax[n + 1]
、ymin[n + 1]
分别记录每行的最大纵坐标、最小纵坐标、每列的最大横坐标、最小横坐标。这样可以方便地通过行或列的索引快速访问对应的最大和最小坐标值。选择INT_MAX
作为初始值是因为它是一个很大的数,可以确保在后续的更新过程中,第一次遇到实际坐标值时能够正确地更新最小坐标值。 -
遍历棋子坐标:当读取到一个棋子的坐标
(x, y)
时,更新对应的行和列的最大和最小坐标值。这是因为如果两个棋子在同一行或同一列,那么它们之间可以连线,而连线的长度就是该行或该列上两个棋子纵坐标之差(对于行)或横坐标之差(对于列)。通过不断更新最大和最小坐标值,可以在后续计算中得到该行或该列上任意两个棋子之间的最大距离。 -
计算最长连线长度:在第二次遍历中,对于每一行和每一列,分别计算最大纵坐标与最小纵坐标之差以及最大横坐标与最小横坐标之差,取其中的较大值。这是因为连线的长度是由行或列上两个最远棋子之间的距离决定的,而这个距离可以通过最大和最小坐标值之差得到。不断更新
res
,使其始终保持最长连线的长度。最后输出的res
就是整个棋盘上最长连线的长度。
我们N个真是太厉害了
题目描述
登录—专业IT笔试面试备考平台_牛客网
运行代码
#include <iostream>
#include <vector>typedef long long i64;int main() {int t;std::cin >> t;while (t--) {int n;std::cin >> n;std::vector<int> c(n + 1, 0);for (int i = 1; i <= n; ++i) {int x;std::cin >> x;if (x <= n) c[x]++;}i64 sum = 0;bool found = false;for (int i = 1; i <= n; ++i) {if (!c[i] && sum < i) {std::cout << i << '\n';found = true;break;}sum += static_cast<i64>(c[i]) * i;}if (!found) std::cout << "Cool!\n";}return 0;
}
代码思路
一、整体思路
- 首先读取测试数据组数
t
。 - 对于每组测试数据:
- 读取小朋友的数量
n
。 - 创建一个大小为
n + 1
的向量c
,并初始化为全零,用于统计每个数字出现的次数。 - 遍历输入的每个小朋友手中的小星星数量
x
,如果x
小于等于n
,则将c[x]
的值加一,表示数字x
出现了一次。 - 初始化一个变量
sum
为 0,用于累计可以由小朋友手中星星组成的数字总和。 - 从 1 到
n
遍历:如果当前数字i
在向量c
中对应的次数为 0(即!c[i]
),并且累计总和sum
小于i
,说明找到了一个无法由小朋友手中星星组成的最小数字,输出该数字并设置found
为 true,表示找到了答案。如果没有找到无法组成的数字,则将c[i]
乘以i
的值累加到sum
中,表示将数字i
出现的次数乘以其本身的值加到总和中。 - 如果遍历完整个范围都没有找到无法组成的数字,则输出
"Cool!"
。
- 读取小朋友的数量
二、原理分析
-
统计数字出现次数:
- 使用向量
c
来统计每个数字在小朋友手中星星数量中出现的次数。这样可以快速确定某个数字是否存在以及出现的次数。 - 只考虑小于等于
n
的数字,因为问题要求找到n
以内无法组成的最小数字。
- 使用向量
-
累计总和与判断:
sum
变量用于累计可以由小朋友手中星星组成的数字总和。通过遍历从 1 到n
的数字,检查是否存在某个数字无法由已有的星星数量组成。- 如果当前数字
i
在向量c
中对应的次数为 0,说明这个数字没有出现在小朋友手中的星星数量中。同时,如果累计总和sum
小于i
,那么就找到了一个无法组成的最小数字。 - 例如,如果已经有数字 1 和 2,那么可以组成的数字总和为 3(1 + 2)。如果下一个数字 3 在向量
c
中对应的次数为 0,并且sum
(当前为 3)小于 4,那么就找到了无法组成的最小数字 4。
-
输出结果:如果找到了无法组成的数字,则输出该数字。如果遍历完整个范围都没有找到无法组成的数字,则输出
"Cool!"
,表示可以组成n
以内的任意正整数。