题意:就是给定n个数字,找到一个子序列,里面不同的数不超过k。
思路:定一个起点stt,然后向后遍历,找到最大长度的序列,用max记录,记录一次后,起点向后移动,注意起点向后移动时要移动几位,有时不一定是移动一位。
代码如下:
#include<cstring>
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
int a[500005];
int vis[1000005];//记录这个数出现的次数
int main(){
int i,j,t,n,k,cnt=0,stt,maxx=0,maxst=1;
scanf("%d%d",&n,&k);
stt=1;//起点设置为1
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
if(cnt<=k){if(vis[a[i]]==0)cnt++;vis[a[i]]++;}//要找到最大长度的good数,所以在不同数的数目小与或等于的时候要继续往后找
if(cnt>k){//直到找到刚好超过k个时,然后去掉当前的数,才是最大的
if(i-stt>maxx){maxx=i-stt;maxst=stt;}//与最大长度比较,并且记录最大长度和最大长度的起点
while(vis[a[stt]]-1>0){//从首位开始去掉若干数字,并且要保证必须去掉一个只出现过一次的数字,这样cnt才会减1
vis[a[stt]]=vis[a[stt]]-1;
stt++;//起点往后移动
}
if(vis[a[stt]]-1==0){//找到了只出现过一次的数字
vis[a[stt]]=vis[a[stt]]-1;
stt++;
}
cnt--;//计数器减1,继续往后
}
}
i=i-1;//因为for循环后面多执行了一次i++
if(cnt<=k){//最后不管cnt是小与还是等于k都要比较了
if(i-stt+1>maxx){
maxx=i-stt+1;maxst=stt;
}
}
printf("%d %d\n",maxst,maxst+maxx-1);
return 0;
}