【洛谷刷题 | 第七天】

本系列文章我将总结我在刷算法题所用到的知识,如果你也在刷算法并且是新手,我相信这系列文章会很适合你。

今日题目:

【洛谷刷题 | 第七天】

    • 今日题目:
      • [1.CSP-J 2020 直播获奖(模拟,排序)](#1.[CSP-J 2020] 直播获奖(模拟,排序))
      • [2. 语言月赛 202404 道法考试(模拟,数组)](#2. [语言月赛 202404] 道法考试(模拟,数组))
    • 总结:

1.CSP-J 2020 直播获奖(模拟,排序)

链接:P7072 CSP-J 2020 直播获奖

依次读入 n 名选手成绩,每加入第 p 个选手后,用整数运算算出计划获奖人数

max(1,p×w÷100),取当前排名前该人数的最低成绩作为分数线,同分全部保留晋级,按顺序输出每一步实时分数线;成绩值域仅 0~600,n 最大10的5次方,禁止浮点计算防止精度出错。

案例:

cpp 复制代码
输入                                                        输出
10 60                                     200 300 400 400 400 500 400 400 300 300      
200 300 400 500 600 600 0 300 200 100

我当时想的是用set容器,因为它有自动排序的优点,但有一个致命的错误就是它会把重复的数据给删除掉,那能不能输入一个再重新排序,算出结果,先不说可不可以,这样算的复杂度特别高,当我们再次回看题目就可以发现,其实它的分数是有限制 的,而且数据不大,最高只有600,所有可以利用成绩值域仅 0~600的特点,用计数数组统计每个分数的出现次数,每录入一个选手成绩就更新计数数组,通过整数运算算出当前计划获奖人数,再从高分到低分累加统计人数,直至累加人数满足获奖要求,此时的分数即为实时分数线,依次输出即可。

题解:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int c[601];
int main()
{
    int n,w;
    cin>>n>>w;
    int a;
    int k;
    int line = 0;
    for(int i=1;i<=n;i++)
    {
        int sum =0;
        cin>>a;
        c[a]++;
        k = i*w/100;
        k = max(1,k);
        for(int j=600;j>=0;j--)
        {
            sum+=c[j];
            if(sum>=k){
                line = j;
                break;
            }
        }
          cout<<line<<" ";
    }
  
    
}

2. 语言月赛 202404 道法考试(模拟,数组)

链接:B3966 语言月赛 202404 道法考试

有 n 道题目,每题标准答案含 m 个知识点,依次读入每题标准答案与作答知识点,若每题作答完全包含对应全部标准答案知识点则得 2 分否则得 0 分,最后输出总分。

第一行两个整数 n 和 m,第 2∼n+1 行每行 m 个整数,第 i 行的内容表示第 i−1 题标准答案包含的知识点编号,保证单个题目的知识点编号没有重复,用空格隔开。从第 n+2 行到第 2n+1 行依次输入每题的作答内容,每行第一个整数是该题作答的知识点个数 l i l_i li,其后紧跟着 l i l_i li 个整数,代表这道题实际作答的所有知识点编号。

案例:

cpp 复制代码
输入                                       输出
2 2                                        2
1 3
4 6
2 1 4
7 1 2 3 4 6 7 8

这道题我最先想的是用容器把它们存起来,然后比较容器相不相同,但这样结果肯定是错的,因为只有作答和标准答案相等,这个方法才可以,但题干明确说明,只要作答包含了标准答案就是对的

其实这道题难的点就是想到用数组 这个方法,

可以先把每道题的标准答案存储在二维数组里,然后依次读取每道题的作答内容,用布尔数组标记作答过的知识点,接着检查这道题的所有标准答案知识点是否都被标记过,全部包含就加 2 分,最后输出总得分。

题解:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int a[1009][1009];
bool v[5009] = {false};
int main()
{
    int n,m;
    cin>>n>>m;
    int sum =0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
   
    int c;
    for(int i=1;i<=n;i++)
    {   
        memset(v, 0, sizeof(v));  
         int k;
         cin>>k;
        for(int j=0;j<k;j++)
        {
             cin>>c;
            v[c] = 1;
        }
         bool ok = 1;
        for(int j=1;j<=m;j++)
        {
            if(!v[a[i][j]]) {
                ok =0;
                break;
                
            }
        }
       if(ok) sum+=2;
    }
  cout<<sum;
}

总结:

今天的题目都是考察的代码思路 ,不能一上来就套用熟悉的容器和暴力排序,要先仔细审题观察数据特点。第一题直播获奖我一开始想用 set 自动排序,却忽略它会去重的缺陷,暴力排序又会超时,后来发现分数值域极小,改用计数数组高效统计;第二道法考试我最初想直接对比容器是否相等,误解题目只需包含而非完全一致,最后用标记数组判断元素包含关系。两道题都提醒做题要先避开思维定式,观察题目隐藏的数据范围与规则条件,选择更贴合题意、效率更高的解法,而不是盲目套用固定模板。

最后:

(这几天都去刷算法了,就没怎么更新,这次也非常幸运,做到了近几次最简单的题,所以就稳稳过了,把这份幸运分享给大家)

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

相关推荐
退休倒计时9 分钟前
【每日一题】LeetCode 15. 三数之和 TypeScript
数据结构·算法·leetcode·typescript
林爷万福15 分钟前
MATLAB光谱数据分析从入门到项目实战
算法·光纤光谱仪
吴可可12321 分钟前
AutoCAD2016二次开发环境配置指南
算法·机器学习
一条大祥脚25 分钟前
ABC461 枚举|扫描线|动态前缀和|数论|dfs枚举子集
算法·深度优先
计算机安禾28 分钟前
【数据库系统原理】第14篇:关系模式的语义约束:函数依赖的公理系统与闭包计算
人工智能·算法·机器学习
量化君也29 分钟前
快速入门量化交易都要学些什么?
大数据·人工智能·python·算法·金融
AbandonForce40 分钟前
滑动窗口:定长滑动窗口与不定长滑动窗口
数据结构·c++·算法
炸薯条!1 小时前
二叉树的链式表示(2)
java·数据结构·算法
Tairitsu_H1 小时前
[LC优选算法#2] 滑动窗口 | 长度最小的子数组 | 无重复字符的最长子串 | 最大连续1的个数
算法
小欣加油1 小时前
leetcode3689最大子数组总值I
c++·算法·leetcode·职场和发展·贪心算法