hdu2158

 

最短区间版大家来找碴

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

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
3 2
Hint
第二个查询,找到的区间是[4,5]
 

这道题就是每次询问确定最初的l,r然后l向右移动并维护r使得m个数总是包括,求最短区间就行

 

在这里给出一组数据:

5 1

5 0 4 4 5

2

4 5

没想到这组数据前我无限wa抓狂

 

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<string>

#include<queue>

#include<algorithm>

#include<map>

#include<iomanip>

#define INF 99999999

using namespace std;



const int MAX=100000+10;

int s[MAX],num[MAX],pos[MAX];//pos记录i的第一个位置

int mark[MAX];



int main(){

	int n,m,q,a;

	while(cin>>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,maxlen=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]];

			maxlen=r-l+1;

			while(r<n){

				--num[s[l]];

				if(num[s[l]] == 0){

					while(++r<n && s[r] != s[l])++num[s[r]];//维护r时区间[l,r]包含m个数 

					num[s[r]]=1;

				}

				while(++l<=r && mark[s[l]] != i);//l每次都到下一个输入过的点 

				if(r<n && maxlen>r-l+1)maxlen=r-l+1;

			}

			cout<<maxlen<<endl;

		}

	}

	return 0;

}


 

 

你可能感兴趣的:(HDU)