P1638 逛画展

题目描述

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

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

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

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

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

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

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

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

输入格式

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

所绘画的。

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

输出格式

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

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

输入输出样例

输入 #1

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

输出 #1

1
2 7

题意:求包含 m 个不同元素的最短子区间

1、尺取法 ,对于区间 [ l , r ] , 像右延申 r 直到该区间满足包含 m 个元素,更新答案,左端点 l + 1,继续下一个区间。

2、二分,二分区间长度 d , 然后判断整个区间即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const int MAX=1000000+10;
int n,m,a[MAX],d[2000+10],ans,L,R;
int main(){
freopen("in","r",stdin);
sf(n);sf(m);
fi(i,1,n+1)
sf(a[i]);
int l=1,r=0,cnt=0,ans=INF;
while(l<=n){
while(r<n && cnt < m){
r ++ ;
if(!d[a[r]]) cnt ++;
d[a[r]]++;
}
if(cnt < m) break;
if(ans > r-l+1){
ans = r-l+1;
L=l;R=r;
}
ans = min(ans,r-l+1);
cnt -= !--d[a[l++]];
}
printf("%d %d",L,R);
return 0;
}