最短区间版大家来找碴
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;
}