[noip模拟]画展<队列的基础知识>

Description

博览馆正在展出由世上最佳的M位画家所画的图画。人们想到博览馆去看这几位大师的作品
。可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,a和b,
代表要看展览中的第a幅至第b幅画(包含a和b)之间的所有图画,而门票的价钱就是一张图画
一元。人们希望入场后可以看到所有名师的图画(至少各一张)。可是又想节省金钱……请你
写一个程序决定购买门票时的a值和b值。

Input

第一行是N和M,分别代表博览馆内的图画总数及这些图画是由多少位名师的画所绘画的。
其后的一行包含N个数字,它们都介于1和M之间,代表该位名师的编号。
N<=1000000,M<=2000

Output

a和b(a<=b)由一个空格符所隔开。
保证有解,如果多解,输出a最小的。

Sample Input

12 5
2 5 3 1 3 2 4 1 1 5 4 3

Sample Output

2 7


这道题可能是我博客里最简单的一道题,但是可怕的是,我还是错了几次,这确实有点绝望。我的错误原因就是我自己认为一旦收集齐m个数字就跳出,但其实没有考虑到有可能在后面会有更小的值

当然这种错误真的是脑子抽了,这题的思路超级简单,就是一个O(n)复杂度的队列模拟,如果队首可以收缩,那就收缩;
好吧这就是全部思路,好吧题如此简单,我也就提供一个精简过后的代码吧
 1 #include<iostream>
 2 #include<queue>
 3 using namespace std;
 4 int vis[2005],n,m,a,l=1,r,tot,ans=1000005,al,ar;    queue<int>q;
 5 int main(){cin>>n>>m;
 6     for(int i=1;i<=n;i++){
 7         cin>>a;    q.push(a);    r++;
 8         if(vis[a] == 0){tot++;}    vis[a]++;
 9         while(vis[q.front()] > 1 && l < r){l++;    vis[q.front()]--;    q.pop();}
10         if(tot==m){if(r-l+1<ans)ans=r-l+1,al=l,ar=r;    }
11     }cout<<al<<' '<<ar;
12 } 
View Code


原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7517773.html