NEFU 大一寒假训练十一(map)2020.02.17

Summary

今天的题终于少了一些,不过有点坑,被罚时罚死了 /(ㄒoㄒ)\~~
昨天 题目预测 命中率 2/4=50%,没想到只有 4 题 ヾ(≧▽≦*)o

Information

No.TitleAC/Submit
A保龄球-map55/199
B查字典62/88
C眼红的Medusa49/151
D指数序列16/95

Problem A: 保龄球-map (1687) [55/199]

Tips

一个简单的签到题,用 map 保存瓶子的位置即可
注意:本题使用 cin cout 会 TLE !!!(cost + 20)

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
    long long n,num,m;
    map<long long,int>ma;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
    	scanf("%lld",&num);
    	ma[num]=i;
	}
	scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
    	scanf("%lld",&num);
    	printf("%d\n",ma[num]);
	}
    return 0;
}

Problem B: 查字典 (1678) [62/88]

Tips

一个模板题,可以练练 mapstring
好吧 ╮(╯-╰)╭ 这才是真正的签到题。

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,num,m;
    map<string,int>ma;
    string word;
    cin>>n;
    while(n--)
    {
    	cin>>word>>num;
    	ma[word]=num;
	}
	cin>>m;
	while(m--)
	{
		cin>>word;
		cout<<ma[word]<<endl;
	}
    return 0;
}

Problem C: 眼红的Medusa (1686) [49/151]

Tips

这题有个坑,绕过去就不难了。

输出一行,为获得两个奖项的人的编号,
按在科技创新奖获奖名单中的先后次序输出

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
    long long n,num,m,kc[100000];
    map<long long,int>ma;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
    	cin>>kc[i];
    	ma[kc[i]]++;
	}
	for(int i=0;i<m;i++)
    {
    	cin>>num;
    	ma[num]++;
	}
	for(int i=0;i<n;i++)
	{
		if(ma[kc[i]]==2)cout<<kc[i]<<" ";
	}
    return 0;
}

Problem D: 指数序列 (1677) [16/95]

Tips

一道数学题,分析一下就出来了:

题目分析:
给出 a1 ,a2 ,…,an,可以对应的找到 2a1 ,2a2 ,…,2an
问至少添加多少个 2x 的数(x 为非负整数),能使这个序列所有整数和为 2v-1,其中 v 是任意的。

思路分析:
掏出万能的 Win10 计算器观察二进制,发现要想满足题目要求,
只需 使二进制所有位都为 1,也就是要 找最高位之前 0 的个数,用一个数进行补充。
首先题目中的数据给的就是二进制位数,那么现在只需关心两方面:

  1. ai 的最高位数
  2. 最高位之前有几个 1(减一下得到 0 的数量)

那么再来看一下数据范围:每个数最大 2e9,肯定不能循环遍历,那就用新讲的 map 存。
map 的 key 保存第几个二进制位(即 ai ),value 保存这位有几个
这时你会发现题中还有一个重要信息:“这个序列保证单调不降”
这就说明两个同样的位数会产生进位,
解决方案也很简单:map 存储的时候个数只要有 2 个就进位

思路理解了,写代码就不难了。

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
    long long maxa=0,num,cnt=0,ans;
    map<long long,int>ma;
    scanf("%lld",&n);
    while(n--)
    {
    	scanf("%lld",&num);
    	ma[num]++; //个数++
    	if(ma[num]==2)
    	{
    		for(long long i=num;ma[i]==2;i++) //进位
    		{
    			ma[i]-=2;
    			ma[i+1]++;
			}
		}
	}
    for(map<long long,int>::iterator it=ma.begin();it!=ma.end();it++)
	{
		if(it->second!=0) //-2之后会留下这个pair,所以要判断一下是否被减到0
		{
			cnt++; //计算1的个数
			if(it->first>maxa)maxa=it->first; //找到最大位数
		}
	}
	printf("%lld",maxa<cnt?0:maxa-cnt+1);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值