版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/violinlove/article/details/83112942
传送门:https://www.luogu.org/problemnew/show/P1638
解析:
尺取法 求刚好拥有所有m种数字的最短区间.
设置l,r两个指针,并用一个变量 cnt 统计一段区间中的不同数字个数,
不满足条件时,r++
满足条件时更新答案,并判断当前 l 位置的数字在 l~r 这个区间中是否有两个及以上
有的话,不改变cnt 直接l++
只有一个的话,cnt--,并且 l++
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 1000006
#define M 2005
using namespace std;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
int n,m;
int a[N];
int cal[M];
bool vis[M];
int main (){
n=wread();m=wread();
for (int i(1);i<=n;++i)
a[i]=wread();
int cnt(0);
int l(1),r(0);
int ans(0x7f7f7f7f),pos1(0),pos2(0);
while (r<=n){
while (cnt<m && r<=n ) {
r++;
int nx(a[r]);
if (vis[nx]) cal[nx]++;
else vis[nx]=true,cal[nx]=1,cnt++;
}
if (cnt==m)
if (ans>r-l+1)
ans=r-l+1,pos1=l,pos2=r;
if (r>n) break;
int nx(a[l]);
if (cal[nx]>1) {
cal[nx]--;
l++;
}
else {
cal[nx]=0;
vis[nx]=false;
cnt--;
l++;
}
}
printf("%d %d\n",pos1,pos2);
return 0;
}