小浣熊干脆面

来源:互联网 发布:js数组按数字大小排序 编辑:程序博客网 时间:2024/05/16 00:57

问题描述


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袋


测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助测试用例 2以文本方式显示
  1. 12 5↵
  2. 2 5 3 1 3 2 4 1 1 5 4 3↵
以文本方式显示
  1. 6↵
1秒64M0
题解思路

大致思路:

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

具体实现:

设一个数组用作队列,在一开始的时候把一个包含所有种类面面的数串读进队列里面,并记录每种面面出现的次数(为了后面的删操作)。然后就是一个一个的读数字,读一个数字,将这个数字的出现次数加一,然后从队列的最前面开始搜索,如果该元素出现的次数大于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>


0 0
原创粉丝点击