2020年OJ习题【map】

map翻译为映射,是STL中的常用容器。其实,数组就是一种映射,比如:int a[100];就是定义了一个int到int的映射。而a[5]=25;就是把5映射到25。数组总是将int类型映射到其它基本类型(称为数组的基类型),这同时也带来了一个问题,有时候我们希望把string映射成一个int,数组就不方便了。这时就可以使用map,map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器)。

要使用map,必须先添加map头文件,即#include ,同时必须要有“using namespace std”。
定义一个map的方法为:map<typename1,typename2> name;
其中,typename1是映射前的类型(键key),typename2是映射后的类型(值value),name为映射的名字。
普通int数组a就是map<int,int> a。而**如果是字符串到整型的映射,就必须使用string,而不能使用char,即map<string,int> a。**map的键和值也可以是STL容器,比如:map<set,string> mp。当然,map的键和值都是唯一的。

访问 map 的元素有两种方式,一种是通过下标访问;另一种是通过迭代器访问。
通过下标访问就像普通的数组元素访问,例如先定义map<char,int> mp,然后就可以通过mp[‘c’]的方式来访问它对应的元素,如mp[‘c’]=124。
通过迭代器访问,先作如下定义:
map<typename1,typename2>::iterator it;
因为map的每一对映射都有两个typename,所以,我们使用“it->first”来访问键,而使用“it->second”来访问值。

map常用函数:
(1)find()和 size()
find(key)是返回键为 key 的映射的迭代器,时间复杂度为 0(log 2 n),n 为 map 中映射的对数。size()用来获得map中映射的对数,时间复杂度为O(1)。
(2)clear()
clear()用来清空 map,时间复杂度为 0(n)。
(3)erase()
erase()可以删除单个元素,也可以删除一个区间内的所有元素。
删除单个元素可以用:erase(it),it为要删除的元素的迭代器,时间复杂度为O(1)。
也可以用:erase(key),key为要删除的映射的键,时间复杂度为O(log2n)。
删除一个区间内的所有元素用:erase(first,last),first为区间的起始迭代器,last为区间的末尾迭代器的下一个地址,也就是左闭右开的区间[first,last),时间复杂度为O(last-first)。

保龄球-map

map的key存得是保龄球数,value存得是位置
注意这里输出不能用cout,会超时

#include <bits/stdc++.h>
using namespace std;
map<int,int>vis;
int n,q,m,p;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>p;
        vis[p]=i;
    }
    cin>>q;
    while(q--)
    {
        cin>>m;
        if(vis[m])
            printf("%d\n",vis[m]);
        else
            printf("0\n");
    }
    return 0;
}

查字典

模板题

#include <bits/stdc++.h>
using namespace std;
map<string,int>vis;
string name;
int p,m,n;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>name;
        cin>>vis[name];
    }
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>name;
        cout<<vis[name]<<endl;
    }
    return 0;

眼红的Medusa

这题有意思,一开始一直不知道错哪里了,结果再一看题目,要求按前者的顺序输出hhh。。。。。。

#include <bits/stdc++.h>
using namespace std;
map<int,int>vis;
int x,m,n,a[100005],b[100005];//a存第一个奖项的得主编号,b存两个奖项的得主编号,x输入第二个奖项的得主编号
int main()
{
    cin>>n>>m;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];//第一个奖项得主先不用放map里
    }
    for(int i=1;i<=m;i++)
    {
        cin>>x;
        vis[x]++;//先放第二个奖项的得主
    }
    for(int i=1;i<=n;i++)
    {
        if(vis[a[i]])//在这里判断是否是两个奖项得主
            b[++cnt]=a[i];
    }
    for(int i=1;i<=cnt;i++)
    {
        i==cnt?cout<<b[i]:cout<<b[i]<<" ";
    }
    return 0;
}

指数序列

万恶的二进制,一到了这种题,我脑子就不够用。。。。。。

一个由 n 个非负整数组成的序列 a1 ,a2 ,…,an 。这个序列保证单调不降。
另一个序列 2^a1 ,2^a2 ,…,2^an,最少要在这个序列中添加多少个形式为 2^x 的数(x 为非负整数),才能使这个序列所有整数的和为 2^v-1 ,其中 v 为某个非负整数。
思考到用二进制的思想(不然都是2的幂次是干嘛的。。。。。。)
只有当二进制的每一位都是1的时候才满足题意,有几个0,就加上几个数,这就是最少的,因此题目的意思就是要找二进制有几位是0,考虑到题目的数范围很大,因此不能用数组,要用map,而且要注意,正因为序列是不降的,所以需要进位,有两个相同的就要进一位!
但是还不能直接找0的个数,因为 序列是单调不降的,所以map的第一个必定是第一个写入的数,这个数可能不是0,比如说第一个数是3,那么后续的数都是>=3的,所以其实隐藏了第一位,第二位也是0,但是现在直接在map找0,是找不到这两个的,所以要找有多少个1,再找一共有多少位,(这里应该是map里的最高位+1,因为还有第一位(自己理解一下就能明白)),他们的差就是结果了!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,int>vis;
int n,x;
int main()
{
    cin>>n;
    int cnt=0,maxn=0;
    while(n--)
    {
        cin>>x;
        vis[x]++;
        if(vis[x]==2)
        {
            ll i=x;
            while(vis[i]==2)//进位
            {
                vis[i]-=2;
                vis[i+1]++;
                i++;
            }
        }
    }
    map<ll,int>::iterator it;
    for(it=vis.begin();it!=vis.end();it++)
    {
        if(it->second!=0)
            {
                cnt++;//记录1的个数
                if(it->first>maxn)//记录最高位
                    maxn=it->first;
            }
    }
    cout<<maxn+1-cnt<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值