【每日一题】【map和set】RC-v7 熊猫血 C++

2024 睿抗机器人开发者大赛CAIP-编程技能赛-高职组(省赛)

RC-v7 熊猫血

题目描述

在“一年一度喜剧大赛”上有一部作品《少爷和我》,讲的是霸道管家龙傲天和憨厚少爷刘波的故事。管家有着霸总文学主人公所有的毛病,包括会咳出熊猫血……

血型是指血液各成分的抗原在个体间出现的差异。人类血型有数十种类型或系统,庞大复杂,如果把所有分类组合都考虑在内,可以细分出非常多种血型。熊猫血是 Rh 阴性血的俗称,东方人 Rh 阴性血型

非常稀有,只占不到 0.5%。

本题给出一批熊猫血型的数据,请你帮前来查询的人查一下他们是否有熊猫血,最后统计一下他们中间的熊猫血占比是多少。

输入格式

输入首先给出一批熊猫血型的数据:在第一行给出不超过 1 0 4 10^4 104的正整数 N N N,随后 N N N行,每行给出一种熊猫血型的编号,由不超过 8 8 8个大写英文字母和数字组成。题目保证编号不重复。
随后是查询人的信息,首先是一个不超过 1 0 5 10^5 105的非负整数 M M M,随后 M M M行,每行给出一个人的血型编号,格式同上。

输出格式

在第一行中输出 M 个由 0 或 1 组成的串,其中第 i i i位对应第 i i i个查询者,如果是熊猫血则为 1,否则为 0。
第二行输出携带熊猫血者所占的百分比(意思是:有熊猫血的人数/查询总人数 × 100 \times 100 ×100),输出小数点后 2 位。
第三行输出被查询次数最多的那种熊猫血型的编号。题目保证输出存在唯一。

样例 #1

样例输入 #1

3
RH0ABP1
RH0APY
BPYORH0
9
BPYORH1
RH0ABP2
RH0APY
APYORH0
RH0OPY
BPYORH0
RH1APY
RH0APY
ABPYRH0

样例输出 #1

001001010
33.33
RH0APY

提示

代码长度限制 16 KB

Python (python3)
时间限制 400 ms
内存限制 256 MB

Java (javac)
时间限制 1000 ms
内存限制 256 MB

其他编译器
时间限制 200 ms
内存限制 64 MB
栈限制 8192 KB

做题要点

  1. 编号不重复
  2. 查一下他们是否有熊猫血
  3. 计一下他们中间的熊猫血占比是多少
  4. 1 ≤ N ≤ 1 0 4 1\le N \le 10^4 1N104 , 1 ≤ M ≤ 1 0 5 1\le M \le 10^5 1M105
  5. 除开Python和Java以外时间限制 200 ms

做题难点

如何优化代码,使得符合200ms的时间复杂度

仅用map去存储判断,会超时。
给出的正解是用set存储并用set中的count()函数去进行判断

做题思路

首先按照暴力的思路想题目是很简单的。

  1. 记录所有熊猫血的血型编号
  2. 每次输入查询人的信息血型编号就去之前的记录库里面查询一遍。如果查到了,对应熊猫血的血型编号记录个数+1并且记录一下串的第 i i i位为1;否则,记录一下串的第 i i i为为0
  3. 最后将有熊猫血的人数/查询总人数 × 100 \times 100 ×100的答案输出小数点后 2 位。

很显然如果用纯数组去存储熊猫血的血型编号,每次输入查询人的信息都去遍历查询,时间复杂度就会到 O ( n × m ) O(n\times m) O(n×m),百分百超时

问题就在于如何存储和查询更快,首先想到的就是树的数据结构。
在 C++ 标准模板库(STL)中
set底层数据结构是红黑树,查找效率和插入效率都是 O ( log ⁡ n ) O(\log n) O(logn),元素唯一
map底层数据结构是红黑树,查找效率和插入效率都是 O ( log ⁡ n ) O(\log n) O(logn),元素键是唯一,值不是唯一。

所以这道题就应该考虑用set或者map去实现存储和查询。

总思路

  1. 用set记录所有熊猫血的血型编号
  2. 每次输入查询人的信息血型编号就去之前的记录库里面查询一遍。如果查到了,对应熊猫血的血型编号记录个数(用map记录)+1并且输出1,并且有熊猫血的人数+1;否则,输出为0
  3. 最后将有熊猫血的人数/查询总人数 × 100 \times100 ×100的答案输出小数点后 2 位。

时间复杂度分析

set查找效率和插入效率都是 O ( log ⁡ n ) O(\log n) O(logn)
N N N次插入,有 M M M次查询,且最大值比较 N ≤ M N\le M NM
所以总时间复杂度为 O ( M log ⁡ N ) O(M\log N) O(MlogN)

伪代码

在这里插入图片描述

VJ赛时AC代码

优化优化还是 T M ^{TM} TM优化

#include <iostream>
#include <map>
#include <vector>
#include <set>
using namespace std;
const int N = 1e5+10;
int n,m,cnt,maxa;
map<string,int>ma;
map<string,int>mb;
map<int,string>bm;
//map<string,bool>flag;
set<string>flag;
bool a[N];
int ans;
string t;
int main(){
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> t;
        //flag[t] = true;
        flag.insert(t);
        mb[t] = i;
        bm[i] = t;
    }
    cin >> m;
    for(int i=1;i<=m;i++){
        cin >> t;
        if(flag.count(t)){
            ma[t] ++;
            if(maxa < ma[t]){
                maxa = ma[t];
                ans = mb[t];
            }
            printf("1");
            cnt++;
            continue;
        }
        printf("0");
    }
    cout << '\n';
    printf("%.2f\n",(double)cnt/(double)m*100);
    cout << bm[ans];
}

官方答案

#include <bits/stdc++.h>

using namespace std ;

int main()
{
    int n , m , cnt = 0 ;
    cin >> n ;
    set<string> st ;
    map<string,int> mp ;
    int c = 0 ;
    string res = "" , u = "" ;
    for(int i = 0 ; i < n ; i ++)
    {
        string s ;
        cin >> s ;
        st.insert(s) ;
    }
    
    cin >> m ;
    for(int i = 0 ; i < m ; i ++)
    {
        string s ;
        cin >> s ;
        if(st.count(s))
        {
            cnt ++ ;
            res += "1" ;
            mp[s] ++ ;
        }
        else res += "0" ;
    }
    for(auto [s,v] : mp)
        if(v > c)
        {
            c = v , u = s ;
        }
    cout << res << "\n" ;
    double x = cnt * 100.0 / (m * 1.0) ;
    printf("%.2lf\n",x) ;
    cout << u << "\n" ;
    return 0 ;
}
  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值