超市正在特价售卖巧克力,正好被贪吃的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<bits/stdc++.h>
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;
}