【洛谷刷题 | 第七天】

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

今日题目:

【洛谷刷题 | 第七天】

    • 今日题目:
      • [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 自动排序,却忽略它会去重的缺陷,暴力排序又会超时,后来发现分数值域极小,改用计数数组高效统计;第二道法考试我最初想直接对比容器是否相等,误解题目只需包含而非完全一致,最后用标记数组判断元素包含关系。两道题都提醒做题要先避开思维定式,观察题目隐藏的数据范围与规则条件,选择更贴合题意、效率更高的解法,而不是盲目套用固定模板。

最后:

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

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

相关推荐
故事和你912 小时前
洛谷-入门4-数组3
开发语言·数据结构·c++·算法·动态规划·图论
玉树临风ives2 小时前
atcoder ABC 451 题解
c++·算法·atcoder
_日拱一卒2 小时前
LeetCode:和为K的子数组
算法·leetcode·职场和发展
周可温8412 小时前
动手学RAG
算法
周可温8412 小时前
Transformer 深度理解与动手实现
算法
扶摇接北海1762 小时前
洛谷:B4488 [语言月赛 202602] 甜品食用
数据结构·c++·算法
直有两条腿2 小时前
【机器学习】K-Means 算法
算法·机器学习·kmeans
A923A2 小时前
【洛谷刷题 | 第十天】
算法·洛谷·sprintf·sscanf
Mr_Xuhhh2 小时前
LeetCode 热题 100 刷题笔记:数组与排列的经典解法
数据结构·算法·leetcode