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;
}
相关推荐
计算机安禾2 小时前
【C语言程序设计】第28篇:指针的概念与指针变量
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
lxh01132 小时前
串联所有单词的子串
算法
像污秽一样2 小时前
算法设计与分析-习题5.4
数据结构·算法·排序算法
七夜zippoe2 小时前
Redis高级数据结构实战:从Stream到HyperLogLog的深度解析
数据结构·数据库·redis·python·缓冲
IronMurphy2 小时前
【算法二十四】101. 对称二叉树 543. 二叉树的直径
数据结构·算法·leetcode
qingy_20462 小时前
Java基础:数据类型
java·开发语言·算法
小璐资源网2 小时前
排序算法概览:十大排序算法一览
数据结构·算法·排序算法
Allen_LVyingbo2 小时前
PostgreSQL动态分区裁剪技术:查询性能优化解析(2026年版)
数据库·算法·观察者模式·postgresql·性能优化·架构
少许极端2 小时前
算法奇妙屋(三十二)-DFS解决floodfill问题
算法·深度优先·dfs·floodfill