7-5 好吃的巧克力

超市正在特价售卖巧克力,正好被贪吃的Lucky_dog看见了。

巧克力从左到右排成一排,一共有N个,M种。

超市有一个很奇怪的规定,就是你在购买巧克力时必须提供两个数字a和b,代表你要购买第 a 个至第 b 个巧克力(包含 a 和 b)之间的所有巧克力。

假设所有巧克力的单价均为1元。Lucky_dog想吃所有种类的巧克力,但又想省钱。作为Lucky_dog的朋友,他请你来帮他决定如何选择购买巧克力时的 a 和 b。
输入格式:

第一行包含两个正整数 N 和 M(M<=N, N<=10^6 , M<=2000),分别代表巧克力的总数及种类数。

第二行包含 N 个整数,这些整数均在1 至 M 之间,代表对应的巧克力所属的种类。
输出格式:

输出仅一行,包含两个整数a和 b(a<=b) ,由一个空格隔开,表示花费最少且包含所有种类巧克力的购买区间。

数据保证有解,如果存在多个符合条件的购买区间,输出a最小的那个。
输入样例:

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

输出样例:

在这里给出相应的输出。例如:

2 7

坑:枚举两个坐标的话最后一个点TLE,必须O(n)才能过。

#include
using namespace std;
int a[1000000];
int main(){
	int n,m;cin>>n>>m;
	int d[m+1]={0};
	for(int i=0;i<n;i++)	cin>>a[i];
	int i=0,j=1,min=n,fi=0,fj=n-1;
	int cnt=1;
	d[a[i]]++;
	while(1){
		if(min==m-1)	break;
		if(d[a[j]]==0)	cnt++;
		d[a[j]]++;
		j++;
		while(d[a[i]]>1){
			d[a[i]]--;
			i++;
		}
		if(cnt==m&&min>j-i){
			min=j-i;
			fi=i;fj=j;
		}
		if(i>n-m||j>=n)	break;
	}
	cout<<fi+1<<" "<<fj;
	return 0;
}

你可能感兴趣的:(笔记)