NCSTOJ:逛画展

U : 逛画展
Time Limit:1 Sec Memory Limit:128 MiB
Back Submit Edit

Description
博览馆正在展出由世上最佳的 M 位画家所画的图画,你想到博览馆去看这些才华横溢的大师们的作品。

可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,l和r,代表他要看展览中的第 l 幅至第 r 幅画(包含 l 和 r)之间的所有图画,而门票的价钱就是一张图画一元。

为了看到更多名师的画,你希望入场后可以看到所有名师的图画(至少各一张)。

但是你想要花费最少,现在你需要编写计算机程序,来求出最小花费的的 l 值和 r 值。

Input
第一行是 N 和 M,分别代表博览馆内的图画总数及这些图画是由多少位名师的画所绘画的。

其后的一行包含 N 个数字,它们都介于 1 和 M 之间,代表该位名师的编号。

数据范围:

N<=10^6, M<=2000

Output
l和r(l<=r),中间有一个空格,并且题目保证有解,如果多解,输出l最小的.
Sample Input
12 5
2 5 3 1 3 2 4 1 1 5 4 3
Sample Output
2 7
More Info
题意分析
N个数里求一个区间[l,r],使得这个区间中含有M个不同的数,要求满足条件下,区间长度要最短.

#include<iostream>
#include<deque>
using namespace std;
const int maxn=1000010;
int f[maxn];
int s[2010];//用于记录每种画出现的次数
int l=1,r=maxn;	
deque<int >deq;
int main(){
	//	freopen("qwe.txt","r",stdin);
	int n,m;
	cin>>n>>m;
	int k=0;//记录当前画的种类数

	for(int i=1;i<=n;i++)
	{
	cin>>f[i];
	if(!s[f[i]])++k;//当该种画还没出现时,种类数加一
	deq.push_back(i);//每次都将数据入队
	s[f[i]]++;//对应的画出现次数加一
	while(s[f[deq.front()]]>1)
	{//只要在队列中有与队首相同的画出现就进行队首出队操作
	//s[f[deq.front()]]>1能保证每个画至少出现一次即队首出队后仍能保持对中有该元素
		s[f[deq.front()]]--;
		deq.pop_front();
		
		
		
		
	}
	
	if(k==m&&deq.back()-deq.front()<r-l)
	{//只要当前的长度小于原来记录的长度,就进行边端更新
		r=deq.back();
		l=deq.front();

//至于为什么不用注释中的语句
//s[f[deq.front()]]--;deq.pop_front();这两句即是不加在下次循环while中也会执行
//而while中总能保持画的种类数是不减的所以当画的种类数达到m时就不会在减小了
//		s[f[deq.front()]]--;
//		k--;
//		deq.pop_front();
		
	}
	
	
	

		
		
	}
	
	cout<<l<<" "<<r<<endl;
	return 0;
	
	
	

}

猜你喜欢

转载自blog.csdn.net/qq_42635159/article/details/89398323