0
点赞
收藏
分享

微信扫一扫

hdoj 最短区间版大家来找碴 2158 (爆力模拟)


最短区间版大家来找碴


Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 844    Accepted Submission(s): 297



Problem Description


给定一个序列,有N个整数,数值范围为[0,N)。
有M个询问,每次询问给定Q个整数,可能出现重复值。
要求找出一个最短区间,该区间要包含这Q个整数数值。
你能找的出来吗?




Input


第一行有两个整数N,M。(N<100000, M<1000)接着一行有N个整数。再有M个询问,每个询问的第一行有一个整数Q(Q<100),第二行跟着Q个整数。当N,M同时为0时,输入结束。




Output


请输出最短区间的长度。保证有解。




Sample Input


5 2
1 2 2 3 1
3
1 2 3
3
1 1 3
0 0




Sample Output


Hint


 


//大神写的,,,表示还没看懂。。。找个时间再静心推一下。


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define INF 0x3f3f3f
#define N 100010
using namespace std;
int s[N];
int num[N];
int mark[N];
int pos[N];
int main()
{
	int n,m,q,a;
	while(scanf("%d%d",&n,&m),n|m)
	{
		memset(mark,0,sizeof(mark));
		memset(pos,-1,sizeof(pos));
		for(int i=0;i<n;i++)
		{
			scanf("%d",&s[i]);
			if(pos[s[i]]==-1)
				pos[s[i]]=i;
		}
		s[n]=n;
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&q);
			int l=n,r=-1,mm=INF;
			for(int j=0;j<q;j++)
			{
				scanf("%d",&a);
				num[a]=0;
				mark[a]=i;
				if(pos[a]>r)
					r=pos[a];
				if(pos[a]<l)
					l=pos[a];
			}
			for(int j=l;j<=r;j++)
				num[s[j]]++;
			mm=r-l+1;
			while(r<n)
			{
				num[s[l]]--;
				if(!num[s[l]])
				{
					while(++r<n&&s[r]!=s[l])
						num[s[r]]++;
						num[s[r]]=1;
				}
				while(++l<=r&&mark[s[l]]!=i);
				if(r<n&&mm>r-l+1)
					mm=r-l+1;
			}	
			printf("%d\n",mm);
		}		
	}
	return 0;
}


举报

相关推荐

0 条评论