【编程笔试】美团2021校招笔试-通用编程题第3场(附思路及C++代码)

2023-11-05

练习地址

点此前往练习

小美的仓库整理

小美是美团仓库的管理员,她会根据单据的要求按顺序取出仓库中的货物,每取出一件货物后会把剩余货物重新堆放,使得自己方便查找。已知货物入库的时候是按顺序堆放在一起的。如果小美取出其中一件货物,则会把货物所在的一堆物品以取出的货物为界分成两堆,这样可以保证货物局部的顺序不变。

已知货物最初是按1~n的顺序堆放的,每件货物的重量为w_i,小美会根据单据依次不放回的取出货物。请问根据上述操作,小美每取出一件货物之后,重量和最大的一堆货物重量是多少?

输入描述:

输入第一行包含一个正整数n,表示货物的数量。(1<=n,m<=50000)输入第二行包含n个正整数,表示1 ~ n号货物的重量w_i。(1<=w_i<=100)输入第三行有n个数,表示小美按顺序取出的货物的编号,也就是一个1~n的全排列。

输出描述:

输出包含n行,每行一个整数,表示每取出一件货物以后,对于重量和最大的一堆货物,其重量和为多少。

输入例子1:

5

3 2 4 4 5

4 3 5 2 1

输出例子1:

9
5
5
3
0

例子说明1:

原本的状态是{{3,2,4,4,5}},取出4号货物后,得到{{3,2,4},{5}},第一堆货物的和是9,,然后取出3号货物得到{{3,2}{5}},此时第一堆和第二堆的和都是5,以此类推。

思路:

题中是每次删除序列中的一个元素,要求最大的未删除的元素序列和。由于插入处理比删除简单,因此可以将删除看成插入的逆过程:

开始时,序列是空的,此时最大连续和为0;首先在1号位置插入3,此时最大连续和为3;接着在2号位置插入2,此时最大连续和为5;然后在5号位置插入5,此时最大连续和也为5;最后在3号位置插入4,此时最大连续和为9。

逆序输出上述的最大连续和就是题目所要求的结果了。

那么如何维护插入过程中的连续最大和呢?这里采用记录另一头端点的策略。

即在遍历序列的过程中,维护一个记忆数组mark,使得对每一段连续序列[l,l+1,…,r],mark[l] = r, mark[r] = l。

如果这种性质满足,就只需要对每个元素计算|mark[i] - i|,并取最大值即可。

可以发现,当单独插入一个点u,只需要设置mark[u] = u,就能满足要求,因为u的左右端点都是它本身。

Ref:维护连续最大和思路:点此查看详情

题解:点此查看详情

代码:

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

int main()
{
	int n;
	cin>>n;
	vector<int> w(n),x(n+1);
    //记录连续区间的另一头
	unordered_map<int,int> mark;
    //记录连续区间的和
	unordered_map<int,int> sum;
	vector<int> out(n+1,0);
	for(int i = 0; i < n; i++)
	{
		cin>>w[i];
	}
	for(int i = n; i >= 1; i--)
	{
		cin>>x[i];
		//将排列从{1:n}转换成{0:n-1} 
		x[i]--; 
	}
	for(int i = 1; i <= n; i++)
	{
		int v=x[i];
		mark[v]=v;
		sum[v]=w[v];
		out[i]=max(out[i-1],sum[v]);
		for(auto u:{v-1,v+1})
		{
			auto it=mark.find(u);
			if(it!=mark.end())
			{
				int m=mark[v],n=mark[u];
				mark[m]=n;
				mark[n]=m;
				sum[m]=sum[n]=sum[m]+sum[n];
				out[i]=max(out[i-1],sum[m]);
			}
		}
	}
    //逆序输出
	for(int i = n-1; i >= 0; i--)
	{
		cout<<out[i]<<endl;
	}
	return 0;
}

小美的跑腿代购

小美的一个兼职是美团的一名跑腿代购员,她有n个订单可以接,订单编号是1~n,但是因为订单的时效性,她只能选择其中m个订单接取,精明的小美当然希望自己总的获利是最大的,已知,一份订单会提供以下信息,跑腿价格v,商品重量w kg,商品每重1kg,代购费用要加2元,而一份订单可以赚到的钱是跑腿价格和重量加价之和。小美可是开兰博基尼送货的人,所以自然不会在意自己会累这种事情。请问小美应该选择哪些订单,使得自己获得的钱最多。

请你按照选择的订单编号的从小到大顺序,如果存在多种方案,输出订单编号字典序较小的方案。

输入描述:

输入第一行包含两个正整数n,m,表示订单的数量和小美可以接的订单数量(1<=n,m<=10000)接下来有n行,第i行表示i-1号订单的信息。每行有两个正整数v和w,表示一个订单的跑腿价格和商品重量。(1<=v,w<=1000)

输出描述:

输出包含m个1~n之间的正整数,中间用空格隔开,表示选择的订单编号。

输入例子1:

5 2

5 10

8 9

1 4

7 9

6 10

输出例子1:

2 5

思路:

由于要求输出的是订单编号,因此定义一个pair,存储订单编号和对应的价格。

首先按照价格降序排序,当价格相等时,按照编号升序排序;接着对需要的订单数再进行编号的升序排序。

代码:

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

typedef pair<int,int> Node;

bool compare1(Node a,Node b)
{
	if(a.second==b.second)
		return a.first<b.first;
	return a.second>b.second;
} 

bool compare2(Node a,Node b)
{
	return a.first<b.first;
}
int main()
{
	int n,m;
	cin>>n>>m;
	int v,w;
	Node nums[n];
	for(int i=0;i<n;i++)
	{
		cin>>v>>w;
		nums[i].first=i+1;
		nums[i].second=v+w*2;
		
	}
	sort(nums,nums+n,compare1);
	sort(nums,nums+m,compare2);
	for(int i=0;i<m;i++)
		cout<<nums[i].first<<" ";
	return 0; 
} 

小美的用户名

小美是美团的前端工程师,为了防止系统被恶意攻击,小美必须要在用户输入用户名之前做一个合法性检查,一个合法的用户名必须满足以下几个要求:

  1. 用户名的首字符必须是大写或者小写字母。

  2. 用户名只能包含大小写字母,数字。

  3. 用户名需要包含至少一个字母和一个数字。

如果用户名合法,请输出“Accept”,反之输出“Wrong”。

输入描述:

输入第一行包含一个正整数T,表示需要检验的用户名数量。(1<=T<=100)接下来有T行,每行一个不超过20的字符串s,表示输入的用户名。

输出描述:

对于每一个输入的用户名s,请输出一行,即按题目要求输出一个字符串。

输入例子1:

5

Ooook

Hhhh666

ABCD

Meituan

6666

输出例子1:

Wrong
Accept
Wrong
Wrong
Wrong

思路:

首先判断输入的用户名首字符如果不是字母,就是Wrong;接着遍历输入的用户名字符,对其中的数字和字母进行计数,如果都大于0,才是Accept。

代码:

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

bool Judge(string s)
{
	if(s.size()==0)
		return false;
	if(!isalpha(s[0]))
		return false;
	int digit=0,alpha=0;
	for(int i = 0;i < s.size(); i++)
	{
		if(isdigit(s[i]))
			digit++;
		else if(isalpha(s[i]))
			alpha++;
		else
			return false;
	}
	return alpha>0&&digit>0;
}
int main()
{
	int n;
	string s;
	cin>>n;
	vector<string> out(n);
	for(int i = 0;i < n; i++)
	{
		cin>>s;
		if(Judge(s))
			out[i] ="Accept";
		else
			out[i]="Wrong";
	}
	for(int i = 0;i < n; i++)
	{		
		cout<<out[i]<<endl;
	}
} 

小美的区域会议

小美是美团总部的高管,她想要召集一些美团的区域负责人来开会,已知美团的业务区域划分可以用一棵树来表示,树上有n个节点,每个节点分别代表美团的一个业务区域,每一个区域有一个负责人,这个负责人的级别为A_i。

已知小美召集人员开会必须满足以下几个条件:

  1. 小美召集的负责人所在的区域必须构成一个非空的连通的图,即选取树上的一个连通子图。

  2. 这些负责人中,级别最高的和级别最低的相差不超过k。

请问小美有多少种召集负责人的方式,当且仅当选取的集合不同时我们就认为两种方式不同。由于方案数可能非常大,所以请对109+7取模。

输入描述:

输入第一行包含两个整数n和k,表示区域的数量,和不能超过的级别。(1<=n,k<=2000)接下来有n-1行,每行有两个正整数a和b,表示a号区域和b号区域有一条边。(1<=a,b<=n)最后一行有n个整数,第i个整数表示i号区域负责人的级别。

输出描述:

输出仅包含一个整数,表示可以选择的方案数对109+7取模之后的结果。

输入例子1:

5 1

1 2

2 3

3 4

4 5

2 2 2 2 2

输出例子1:

15

例子说明1:

显然一个区域的方案有{1},{2},{3},{4},{5},两个区域的方案有4个,三个区域的方案有3个,四个区域的方案有2个,五个区域的方案有1个,共15个。

思路:

暴力枚举法:

  1. 枚举所得到连通子图里最小的A[i];
  2. 每次枚举以该值对应的结点i为根DFS建树,一个结点j在这棵树的前提条件是A[i]<A[j] ≤ A[i] + k。

上述枚举思路有一个问题,当数组A中存在重复值时,上述枚举方式会重复计数。因此需要修正一下,将条件改为A[j] ≤ A[i] + k且(A[i], i) < (A[j], j)。

Ref:题解及思路:点此查看详情

以下代码只过了8/10组用例,AC代码详见评论区

代码:

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

vector<vector<int>> graph;
vector<int> level;
int k,i=0;
const int mod = 1e9+7;

int dfs(int u,int pre)
{
	long long out=1;
	for(auto v:graph[u])
	{
		if(v!=pre&&((level[v]>level[i]&&level[v]<=level[i]+k)||(level[v]==level[i]&&v<i)))
		{
			out*=(dfs(v,u)+1);
			out%=mod;
		}
	}
	return out;
}

int main()
{
	int n,r;
	cin>>n>>k;
	int a,b;
	long long out=0;
	graph.resize(n);
	for(int i=1;i<=n-1;i++)
	{
		cin>>a>>b;
		graph[a-1].push_back(b-1);
		graph[b-1].push_back(a-1); 
	}
	for(int i=1;i<=n;i++)
	{
		cin>>r;
		level.push_back(r); 
	}
	while(i<n)
	{
		out=(out+dfs(i,-1)%mod);
		i++;
	}
	cout<<out;
	return 0;
}

总结

第一题:

  1. C++ STL中的unordered_map:无序关联式容器。
    1. unordered_map 容器和 map 容器一样,以键值对(pair类型)的形式存储数据,存储的各个键值对的键互不相同且不允许被修改。
    2. unordered_map 容器底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。
    3. 头文件:#include<unordered_map>
    4. 创建unordered_map容器:unordered_map<T1,T2> umap;
    5. 插入元素:umap.insert(make_pair(a,b));
    6. 删除元素:umap.erase(a);可通过位置和key删除。
    7. 交换2 个 unordered_map 容器存储的键值对:umap1.swap(umap2);前提是必须保证这 2 个容器的类型完全相等。
    8. 容器中键值对个数:umap.size();
    9. 容器所能容纳键值对的最大个数:umap.max_size();
    10. 容器中存储的键 key 对应的值:umap.at(key);如果 key 不存在,则会抛出 out_of_range 异常。
    11. 查找以 key 为键的键值对:umap.find(key);如果找到,则返回一个指向该键值对的正向迭代器;反之,则返回一个指向容器中最后一个键值对之后位置的迭代器。
    12. 在容器中查找以 key 键的键值对的个数:umap.count(key);
    13. 清空容器:umap.clear();

第二题:

  1. 对于sort函数,用它进行排序时,一般都按需求写一个比较规则函数。
  2. 一般的升序和降序排序:
    1. 升序:sort(begin,end,less<data_type>());
    2. 降序:sort(begin,end,greater<data_type());

第三题:

  1. 字符串常用函数
    1. string.size():字符串的长度。
    2. isdigit(s[i]):判断s[i]是否是数字;isalpha(s[i]):判断s[i]是否是字母。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【编程笔试】美团2021校招笔试-通用编程题第3场(附思路及C++代码) 的相关文章

随机推荐

  • 花5分钟判断,你的Jmeter技能是大佬还是小白!

    jmeter 这个工具既可以做接口的功能测试 也可以做自动化测试 还可以做性能测试 其主要用途就是用于性能测试 但是 有些公司和个人 就想用 jmeter 来做接口自动化测试 你有没有想过呢 下面我就给大家讲讲 用 jmeter 如何做接口
  • Linux文件权限一共10位长度,分成四段

    Linux文件权限一共10位长度 分成四段 Linux文件权限 1 文件aaa的访问权限为rw r r 现要增加所有用户的执行权限和同组用户的写权限 下列哪些命令是正确的 a chmod a x g w aaa b chmod 764 aa
  • BSC 及HT 等链的NFT 创造及绑定图片教程

    我们首先打开REMIX 智能合约编程网站 下面代码是NFT合约 Submitted for verification at BscScan com on 2021 10 07 File openzeppelin contracts util
  • RxJava基本流程和lift源码分析

    http blog csdn net lzyzsd article details 50110355
  • WebStorm Debug 配置

    WebStorm 调试配置 所需工具 Chrome 浏览器 Chrome 浏览器插件 JetBrains IDE Support WebStorm 配置过程 首先 下载 Chrome 浏览器以及 JetBrains IDE Support
  • node-第三方模块之nodemailer模块

    nodemailer 模块 专门用来发邮件 下载使用
  • 利用原生js实现TodoList----最简单的待办事项列表(附详细注释)

    利用js实现TodoList 1 todoList html
  • UITableView嵌套WKWebView的那些坑

    最近项目中遇到了一个需求 TableView中需要嵌套Web页面 我的解决办法是在系统的UITableViewCell中添加WKWebView 开发的过程中 遇到了些坑 写出来分享一下 1 首先说一下WKWebView的代理方法中 页面加载
  • 锂电池充放电管理芯片和输出芯片

    锂电池充放电管理芯片 和输出芯片 锂电池充放电管理芯片 关乎锂电池供电的产品 在锂电池上 需要三个电路系统 1 锂电池保护电路 2 锂电池充电电路 3 锂电池输出电路 1 单节的锂电池保护电路 单节为 3 7V 锂电池 也叫 4 2V 和
  • springmvc

    springmvc 前景介绍 springmvc图解 环境搭建 工程起步 springmvc的配置文件 相关的注解 RequestMapping的源码 RequestMapping params PathVariable的作用 Reques
  • 【信号与系统】系统线性时不变、因果稳定性的判定

    1 线性 线性包含均匀性和叠加性 其中均匀性是指输入乘以一个常数 输出也乘一个相同的常数 叠加性是指两个输入信号相加 其对应的输出也是相加关系 判定 假设系统输入E1对应输出R1 输入E2对应输出R2 若信号C1E1 C2E2输入系统后得到
  • Kmeans聚类

    一 特征预处理 1 处理缺失 异常值 缺失值直接补0 异常值可以设置一个阈值 比喻小于数据的1分位数 或者大于95分位数 就把数据进行四舍五入 用相应的分位数赋值 这样可以减少异常值对于聚类的影响 因为聚类一般计算的是距离 有异常值影响会比
  • 谷歌瓦片的网址

    有时我们需要离线谷歌地图 最简单的办法是通过网页获取 网上有很多方法 这里介绍一种非常简单实用的 闲话少叙 先上一个网址 http mt0 google cn vt lyrs s x 0 y 0 z 0 打开后在浏览器中可以看到如下图 这张
  • [第二章 web进阶]文件上传]

    先看一下题目源码
  • dataframe先分组运算再合并输出

    dataframe先分组运算再合并输出 主要用到分组函数groupby和合并函数append concat 具体代码 比如先分组 对每组数据进行删除异常值处理 MAD 然后将处理后的数据合并成一个dataframe输出 import os
  • ArcGIS Maps SDK for Unity 0.3旋转

    ArcGIS Maps SDK for Unity1 0版本已出 基础参考 API https developers arcgis com unity sdk 基础 https cloud tencent com developer new
  • Maple学习(一)Maple的安装

    老板找了高尔夫球的代码 想让我运行得出结果 老板做企业管理的 在代码上比我不着急 又是发Maple教程 又是发文档的 看来我的好日子结束了 Maple系统内置高级技术解决建模和仿真中的数学问题 包括世界上最强大的符号计算 无限精度数值计算
  • vhdx中的win10进行大版本系统升级

    文章目录 前言 普通的win10大版本iso升级方式 vhdx中的win10大版本升级方式 难点分析 无法在虚拟驱动器上安装windows 解决方案 HyperV升级vhdx win10 过程效果图 hyperV虚机创建mbr引导启动项 h
  • Java中如何通过键盘输入一个字符串(数组等相关操作)

    如何在自己的程序中进行键盘输入与输出 废话不多说 直接上代码 第一种 1不限制输入数组的长度 import java util Scanner public class InputArrayNoLimitLength public stat
  • 【编程笔试】美团2021校招笔试-通用编程题第3场(附思路及C++代码)

    导览 练习地址 小美的仓库整理 小美的跑腿代购 小美的用户名 小美的区域会议 总结 练习地址 点此前往练习 小美的仓库整理 小美是美团仓库的管理员 她会根据单据的要求按顺序取出仓库中的货物 每取出一件货物后会把剩余货物重新堆放 使得自己方便