2024年秋招-美团-技术岗-第一批笔试

小美的密码

思路:长度小于正确长度的肯定是要尝试的,假设为x,那么最优的就是下一步登陆成功,也就是x+1,最坏的就是对于所有长度等于正确答案的,最后一次才尝试到正确答案,所以答案就是x+和密码长度相同的字符串个数,需要注意重复的字符串不能计算两次

代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
string s,right_s; 
map<string,bool> mp;
int main()
{
	int n;
	cin>>n;
	cin>>right_s;//存储正确密码 
	int right_len=right_s.size();
	int mx=0,mn=0;
	for(int i=1;i<=n;i++) 
	{
		cin>>s;
		if(mp[s]) continue;//已经出现过就跳过
		mp[s]=true;//标记为已经出现过 
		int len=s.size();
		if(len<right_len)
		{
			mx++;
			mn++;
		}
		else if(len==right_len)
			mx++;
	}
	printf("%d %d",mn+1,mx);
	return 0;
}

小美的数组删除

思路:容易发现,操作2最多执行一次(因为执行一次操作2数组就已经被删除),而且一定是最终执行,但在执行操作2前可能执行操作1,于是我们可以直接枚举在执行操作2前一共执行了多少次操作1,整体复杂度就是O(n)

代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		long long n,k,x;
		scanf("%lld%lld%lld",&n,&k,&x);
		map<int,int> mp;//mp[x]记录数字出现次数 
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			mp[a[i]]++;
		}
		int mex=0;//记录mex 
		for(int i=0;i<=n;i++)
		{
			if(mp[i]==0)
			{
				mex=i; 
				break;
			}
		}
		long long ans=k*mex;//对应于直接执行操作2的情况 
		for(int i=1;i<=n;i++)//枚举在操作2前执行了i次操作1 
		{
			mp[a[i]]--;
			if(mp[a[i]]==0&&a[i]<mex)//更新mex
				mex=a[i];
			ans=min(ans,1ll*i*x+k*mex);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

小美的彩带

思路:容易发现,当剪下来长度大于等于n时,答案就是彩带上的所有颜色,当长度小于n时,我们可以看作两种情况:

情况1:[L,R]在一个彩带上

情况2:[L,R]横跨两个彩带

这里有一个技巧:其实对于循环的彩带而言也就类似于环,我们可以通过把一条彩带复制一倍来等价替换。这里就等价于彩带长度是2*n,前一半和后一半是完全相同的。由于这两种情况对应的长度都是小于n的,我们现在就转化为求解从某一个点开始长度为len的区间中的不同颜色个数。于是自然而然就能想到莫队来做(莫队就是一种利用分块思想来优化暴力求解的方法,不懂的同学可以移步我之前的讲解博客:莫队(离线处理区间询问)_莫队问题-CSDN博客)。需要注意的就是莫队的复杂度是n*sqrt(n),这道题的数据是2*10的五次方,还是比较极限的。由于彩带的颜色有10的9次方种,理论上简单的方法是用map存储颜色,但是map时间耗费比较严重,因此我们需要用数组直接存储,所以需要用到离散化,这里特别需要注意一下。其他就没什么了,下面是代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct node{
	int l,r,id;
}p[N];
int a[N];
int mp[N];//记录每一种颜色出现的次数 
int ans[N];//ans[pl]记录第pl个区间的答案 
int cnt_color;//记录实时区间颜色数量 
void add(int x)
{
	if(mp[a[x]]==0) cnt_color++;//实时区间新加入一个颜色
	mp[a[x]]++;
}
void sub(int x)
{
	mp[a[x]]--;
	if(mp[a[x]]==0) cnt_color--;//实时区间新减去一个颜色 
}
int pn;
bool cmp(node a,node b)
{
	//按照询问左边界所在的块为第一优先级,右边界的大小为第二优先级进行排序
	if(a.l/pn!=b.l/pn) return a.l<b.l;
	return a.r<b.r;
}
vector<int> alls;//用于离散化 
int find(int x)
{
	return lower_bound(alls.begin(),alls.end(),x)-alls.begin()+1;
}
int main()
{
	int n,q;
	cin>>n>>q;
	int cnt=0;//记录总颜色数 
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		alls.push_back(a[i]); 
	}
	sort(alls.begin(),alls.end());
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	cnt=alls.size();
	for(int i=1;i<=n;i++)
	{
		a[i]=find(a[i]);
		a[i+n]=a[i];
	}
	char op[2];
	int len,m=0;//m记录要排序的块数 
	pn=sqrt(2*n);
	int l=1,r=2*n;
	for(int i=1;i<=q;i++)
	{
		scanf("%s%d",op,&len);
		if(len>=n)
		{
			ans[i]=cnt;
			len%=n;
		}
		if(op[0]=='L')
		{
			p[++m].l=l;
			p[m].r=l+len-1;
			p[m].id=i;
			l+=len;
			while(l>n) l-=n; 
		}
		else
		{
			p[++m].l=r-len+1;
			p[m].r=r;
			p[m].id=i;
			r-=len;
			while(r<=n) r+=n;
		}
	}
	sort(p+1,p+m+1,cmp);
	int mo_l=0,mo_r=0;
	for(int i=1;i<=m;i++)
	{
		while(mo_l<p[i].l) sub(mo_l++);
		while(mo_l>p[i].l) add(--mo_l);
		while(mo_r<p[i].r) add(++mo_r);
		while(mo_r>p[i].r) sub(mo_r--);
		if(ans[p[i].id]==0)//还没有填充值 
			ans[p[i].id]=cnt_color; 
	}
	for(int i=1;i<=q;i++)
		printf("%d\n",ans[i]);
	return 0;
}
相关推荐
DuHz18 小时前
论文精读:大语言模型 (Large Language Models, LLM) —— 一项调查
论文阅读·人工智能·深度学习·算法·机器学习·计算机视觉·语言模型
加农炮手Jinx19 小时前
LeetCode 72. Edit Distance 题解
算法·leetcode·力扣
借雨醉东风19 小时前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
_深海凉_19 小时前
LeetCode热题100-打家劫舍
算法·leetcode·职场和发展
jghhh0120 小时前
使用 MATLAB 实现支持向量回归 (SVR) 预测未来数据
算法·matlab
云泽80820 小时前
笔试算法 - 双指针篇(二):四大经典求和题型 + 有效三角形计数问题
c++·算法
qeen8721 小时前
【数据结构】树的基本概念及存储
c语言·数据结构·c++·学习·
一江寒逸21 小时前
数据结构与算法之美:串(字符串)——从基础操作到KMP模式匹配,吃透面试最高频的字符串考点
数据结构·面试·职场和发展
刀法如飞21 小时前
【合并已排序数组的三种实现策略,哪一种更可取?】
算法·程序员
王老师青少年编程21 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【区间贪心】:种树
c++·算法·贪心·csp·信奥赛·区间贪心·种树