小浣熊干脆面

问题描述


Eureka灰常喜欢吃小浣熊干脆面(五香牛肉味,烤肉味,奇奇怪怪味,意大利红烩味,照烧猪排味,香辣蟹味,海苔味,麻辣香锅味,巧克力味,草莓味,玉米味,炸鸡味,奥尔良烤鸡翅味)。以上只是为了馋一下你 ^_^

现在Eureka厌倦了吃干脆面,所以他打算收集齐所有种类的干脆面送给NONO~,但是新一的自动售货机只能买连续的一些干脆面,你能告诉他最少买多少包么?


输入

第一行两个整数n(1 <= n <= 1000000),表示售货机有连续的n袋干脆面, m(1 <= m <= 2000), 表示一共有m种干脆面

第二行有n个整数分别为a1,a2,a2...,an(1 <= ai <= 2000),表示第i袋干脆面是第ai种的


输出

一个整数ans,表示最少购买多少袋(也就是说最短的区间包含1到m所有类型的干脆面,当然Eureka可以等待别人买完前面的一部分再开始买)

样例中Eureka会选择购买5 3 1 3 2 4这一段共6袋


测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 2 以文本方式显示
  1. 12 5↵
  2. 2 5 3 1 3 2 4 1 1 5 4 3↵
以文本方式显示
  1. 6↵
1秒 64M 0
题解思路

大致思路:

运用队列的思路来写,开始的时候先把一个包含所有种类的面面的序列读进队列里面,然后依次向后读数字,每读一个数字就从队列头删去相应的重复的数字。

具体实现:

设一个数组用作队列,在一开始的时候把一个包含所有种类面面的数串读进队列里面,并记录每种面面出现的次数(为了后面的删操作)。然后就是一个一个的读数字,读一个数字,将这个数字的出现次数加一,然后从队列的最前面开始搜索,如果该元素出现的次数大于1就将该元素从队列里面删去,并将该元素的出现次数减一,直到找到一个仅在队列里面出现一次的元素为止。此时利用队列头尾指针来计算队列的长度,更新符合要求的最短长度。就这样直到读完所有的元素之后,输出最短长度即可。

注意事项:

(1)进队列出队列的时候相应指针的变化。

(2)进出队列的时候相应面面出现次数的变化。


实现代码


<span style="font-family:Microsoft YaHei;font-size:14px;">#include<stdio.h>
#include<string.h>
int a[1000010],b[1000010];
int main()
{
	int n,m;
	int i,j,k;
	//int a[1000010];
//	int b[1000010];
	int c[2005];
	int start,end,temp,count;
	int min=1000010;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	start=0;
	end=0;
	count=0;
	for(i=0;count<m;i++)
	{
		b[end]=a[i];
		end++;
		if(c[a[i]]==0)
		{
			count++;
		}
		c[a[i]]++;
	}
		for(j=start;c[b[start]]>1;j++)
			{
				c[b[start]]--;
				start++;
			}
	temp=end-start;
	if(temp<min)
	{
		min=temp;
	}
	for(k=i;k<n;k++)
	{
		b[end]=a[k];
		end++;
		c[a[k]]++;
	//	if(b[start]==a[k])
	//	{
			for(j=start;c[b[start]]>1;j++)
			{
				c[b[start]]--;
				start++;
			}
	//	}
		temp=end-start;
		if(temp<min)
		{
			min=temp;
		}
	}
	printf("%d\n",min);			
	
	
	
	
	
	
	return 0;	
}</span>


你可能感兴趣的:(小浣熊干脆面)