这道题,其实就是搜索,但是有技巧,找到从第一个元素(记为ptr1)开始的包含Q个整数的最短区间长ptr2,然后在对ptr2和ptr1进行搜索,具体的请看代码。

#include<iostream>
using namespace std;
#define L 100010
int a[L]={0},b[L]={0};
bool f[L]={false},g[L]={false};
int main()
{
	int N,M;
	while(cin>>N>>M)
	{
		int i,k=0,x,s=0,sum=0,ptr1=1,ptr2=1,ans=1<<25;
		if((N+M)==0) break;
		memset(f,false,sizeof(f));
		memset(g,false,sizeof(g));
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		for(i=1;i<=N;i++) cin>>a[i];
		while(M--)
		{
			cin>>k;
			sum=0;ans=1<<25;
			memset(f,false,sizeof(f));
			memset(g,false,sizeof(g));
			memset(b,0,sizeof(b));
			for(i=0;i<k;i++)
			{
				cin>>x;
				if(!f[x]) sum++;
				f[x]=g[x]=true;
			}
			s=0;ptr1=ptr2=1;
			for(;s<sum;ptr2++)
			{
				if(g[a[ptr2]])
				{
					s++;g[a[ptr2]]=false;
				}
				b[a[ptr2]]++;
			}
			ptr2--;
			if(ans>(ptr2-ptr1+1)) ans=ptr2-ptr1+1;
			while(ptr1<=ptr2)
			{
				b[a[ptr1]]--;
				if(b[a[ptr1]]==0 && f[a[ptr1]])
				{
					while(ptr2<=N && (a[ptr1]!=a[ptr2]))
					{
						ptr2++;b[a[ptr2]]++;
					}
					if(ptr2>N) break;
				}
				ptr1++;
				if(ans>(ptr2-ptr1+1)) ans=ptr2-ptr1+1;
			}
			if(k==1) ans=1;
			cout<<ans<<endl;
		}
	}
	return 1;
}

 

posted on 2013-05-31 19:48  一路狂奔的人  阅读(289)  评论(0编辑  收藏  举报