P1638 逛画展(尺取)

题目描述

博览馆正在展出由世上最佳的 M 位画家所画的图画。

wangjy想到博览馆去看这几位大师的作品。

可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,

a和b,代表他要看展览中的第 a 幅至第 b 幅画(包含 a 和 b)之间的所有图画,而门票

的价钱就是一张图画一元。

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

可是他又想节省金钱。。。

作为wangjy的朋友,他请你写一个程序决定他购买门票时的 a 值和 b 值。

输入输出格式

输入格式:

 

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

所绘画的。

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

 

输出格式:

 

a和 b(a<=b) 由一个空格符所隔开。

保证有解,如果多解,输出a最小的。

 

求最小区间中满足m类数 尺取

/*
顾名思义,像尺子一样取一段,借用挑战书上面的话说,
尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,
然后根据实际情况不断地推进区间左右端点以得出答案。
尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以说尺取法是一种高效的枚举区间的方法,是一种技巧,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,
无法得出正确答案,所以要先判断是否可以使用尺取法再进行计算。

用两个变量ll和rr来枚举区间

如果ll到rr的区间不满足要求,rr++

如果ll到rr的区间满足要求,记录答案,ll++
*/
#include
using namespace std;
int n,m,a[100005],b[2005],k,ans,l,r,ll,rr;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	 scanf("%d",&a[i]);
	l=1;
	r=1;
	k=1;
	b[a[1]]=1;
	ans=100005;
	while(l<=r&&r<=n)
	{
		if(k==m)
		{
			if(ans>r-l+1)
			{
				ans=r-l+1;
				ll=l;
				rr=r;
			}
			b[a[l]]--;
			if(b[a[l]]==0)
			 k--;
			l++;
		 } 
		 else
		 {
		 	r++;
		 	b[a[r]]++;
		 	if(b[a[r]]==1)
		 	 k++;
		 }
	} 
	printf("%d %d",ll,rr);
	
	
	
	return 0;
}

 

你可能感兴趣的:(P1638 逛画展(尺取))