c++刷题 超能力编程
首先注意到,必须看到所有的画师的画才行,所以可以考虑维护一个区间内,每个画师有多少画,可以用一个数组来维护
第一个循环中,把区间右端点不断右移,并维护该画的画师出现次数,出现新的画师把计数器加一,直到看到所有画师的画,然后循环判断左端点的画师是否出现一次以上,
这时候应用贪心思想,只要出现过一次以上,那么左端点就一定可以弹出,因为这个点的存在只会让区间更长,而不会让区间包含画师更多,我们只要保证这个区间有每个画师的画就行了,
这时用两个变量来记录当前区间左右端点作为初始答案
然后第二次循环,继续循环剩下的画,
每次将右端点+1,维护画的画师出现次数,并不断弹出没必要存在的左端点,因为在第二个循环里任何时刻的区间都保证满足能看到所有画师的画,所以应该在循环里面判断当前区间是否比已知答案的区间更短,如果更短,更新答案
我的代码区间是从零计的,所以输出时+1
虽然循环嵌套,但是因为每个点都只会最多出入一次区间,所以复杂度O(n),只是常数略大.
#include<stdio.h>
int m[2001],num;
int n[1000000];
int main()
{
int R=-1,L=0,N,M,t,i=0,ansL,ansR;
scanf("%d%d",&N,&M);
for(i=0;i<N;i++)
scanf("%d",n+i);
i=0;
while(num!=M)
{
if(m[n[i]]==0)num++;
m[n[i]]++;
R++;
i++;
}
while(m[n[L]]>1)
m[n[L++]]--;
ansL=L;ansR=R;
while(i<N)
{
m[n[i]]++;
R++;
i++;
while(m[n[L]]>1)
m[n[L++]]--;
if(ansR-ansL>R-L)
{
ansR=R;
ansL=L;
}
}
printf("%d %d",ansL+1,ansR+1);
}