牛客周赛 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;
}

代码思路

一、整体思路

  1. 首先从用户输入中读取两个整数 n 和 m,分别代表正数的数量和负数的数量。
  2. 然后使用 std::min 和 std::max 函数求出 n 和 m 中的较小值 minVal 和较大值 maxVal
  3. 根据 n 和 m 的关系计算最长序列的长度并输出。如果 n 和 m 相等,则最长序列长度为 2 * minVal;如果 n 和 m 不相等,则最长序列长度为 2 * minVal + 1

二、原理分析

  1. 确定最小和最大数量:通过求出 n 和 m 的最小值和最大值,可以方便地处理不同情况下的序列长度计算。如果 n 和 m 相等,那么最小数量和最大数量都是同一个值;如果 n 和 m 不相等,那么可以明确区分出较多的数和较少的数。

  2. 计算最长序列长度:当 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;
}

代码思路

一、整体思路

  1. 首先读取棋盘大小 n 和棋子数量 m
  2. 初始化用于记录每行和每列最大和最小坐标值的数组。对于每一行,初始时将最小坐标值设为极大值 INT_MAX;对于每一列同理。
  3. 遍历 m 个棋子的坐标,对于每个棋子的坐标 (x, y):更新 x 行对应的最大纵坐标 xmax[x] 和最小纵坐标 xmin[x]。更新 y 列对应的最大横坐标 ymax[y] 和最小横坐标 ymin[y]
  4. 再次遍历从 1 到 n 的行和列索引:计算每行的最大长度为 xmax[i] - xmin[i],每列的最大长度为 ymax[i] - ymin[i],取其中的较大值。将这个较大值与当前最长连线长度 res 比较,取较大者更新 res
  5. 最后输出最长连线的长度 res

二、原理分析

  1. 数据结构的选择:使用数组 xmax[n + 1]xmin[n + 1]ymax[n + 1]ymin[n + 1] 分别记录每行的最大纵坐标、最小纵坐标、每列的最大横坐标、最小横坐标。这样可以方便地通过行或列的索引快速访问对应的最大和最小坐标值。选择 INT_MAX 作为初始值是因为它是一个很大的数,可以确保在后续的更新过程中,第一次遇到实际坐标值时能够正确地更新最小坐标值。

  2. 遍历棋子坐标:当读取到一个棋子的坐标 (x, y) 时,更新对应的行和列的最大和最小坐标值。这是因为如果两个棋子在同一行或同一列,那么它们之间可以连线,而连线的长度就是该行或该列上两个棋子纵坐标之差(对于行)或横坐标之差(对于列)。通过不断更新最大和最小坐标值,可以在后续计算中得到该行或该列上任意两个棋子之间的最大距离。

  3. 计算最长连线长度:在第二次遍历中,对于每一行和每一列,分别计算最大纵坐标与最小纵坐标之差以及最大横坐标与最小横坐标之差,取其中的较大值。这是因为连线的长度是由行或列上两个最远棋子之间的距离决定的,而这个距离可以通过最大和最小坐标值之差得到。不断更新 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;
}

代码思路

一、整体思路

  1. 首先读取测试数据组数 t
  2. 对于每组测试数据:
    • 读取小朋友的数量 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!"

二、原理分析

  1. 统计数字出现次数

    • 使用向量 c 来统计每个数字在小朋友手中星星数量中出现的次数。这样可以快速确定某个数字是否存在以及出现的次数。
    • 只考虑小于等于 n 的数字,因为问题要求找到 n 以内无法组成的最小数字。
  2. 累计总和与判断

    • sum 变量用于累计可以由小朋友手中星星组成的数字总和。通过遍历从 1 到 n 的数字,检查是否存在某个数字无法由已有的星星数量组成。
    • 如果当前数字 i 在向量 c 中对应的次数为 0,说明这个数字没有出现在小朋友手中的星星数量中。同时,如果累计总和 sum 小于 i,那么就找到了一个无法组成的最小数字。
    • 例如,如果已经有数字 1 和 2,那么可以组成的数字总和为 3(1 + 2)。如果下一个数字 3 在向量 c 中对应的次数为 0,并且 sum(当前为 3)小于 4,那么就找到了无法组成的最小数字 4。
  3. 输出结果:如果找到了无法组成的数字,则输出该数字。如果遍历完整个范围都没有找到无法组成的数字,则输出 "Cool!",表示可以组成 n 以内的任意正整数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值