题目:
https://www.nowcoder.com/acm/contest/13/E
分析:
比赛时以为是栈,后来发现错了,其实是一个滑动窗口的题目;
先用map离散化,所以颜色种数不会超过n;
然后对于每一种颜色,用滑动窗口,向右移动(枚举)序列结尾元素(end),同时合法的开头元素(start)也相映右移;
这里用vector G[i][j] 储存第j个 第i种颜色的子弹所在位置
对于第i种颜色:sum[j]保存第j个这种子弹到第1个这种子弹中间之间有多少个别的颜色的子弹
接下来接下来滑动窗口就好了
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
const int Tmax=100005;
map<int,int> num;
vector<int> G[Tmax];
int n,k,kind,sum[Tmax],ans;
void work()
{
int i,j,len,start,end;
for(i=1;i<=kind;i++)
{
sum[0]=0;
len=G[i].size();
for(j=1;j<len;j++)
{
sum[j]=sum[j-1]+G[i][j]-G[i][j-1]-1;
}
start=0;
for(end=0;end<len;end++)
{
while(sum[end]-sum[start]>k) start++;
ans=max(ans,end-start+1);
}
}
return;
}
int main()
{
int i,tmp;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)
{
scanf("%d",&tmp);
if(num.count(tmp)==0)
{
num[tmp]=++kind;
G[kind].push_back(i);
}
else
{
G[num[tmp]].push_back(i);
}
}
work();
printf("%d",ans);
return 0;
}