hdu2158 最短区间版大家来找碴

题意:
                 最短区间版大家来找碴


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]

思路:

      这个题目做的有点纠结,我的时间复杂度没次询问都是O(N)的,那么一次测试的时间复杂度就是O(N*M)这样是1e了,这样估计就TLE了,但是却AC了,虽然理论上测试数据是随机数据,但是感觉还是有点勉强。我的思路是先找到一个最基本的L,R然后L不停的往后挤,然后维护R来保证当前的区间的正确性,同时更新最小值(这次的代码写的有点挫-_-).


#include<stdio.h>
#include<string.h>

#define N 110000

int num[N] ,markc[N] ,markq[N];

int main ()
{
   int n ,m ,q ,a ,i;
   while(~scanf("%d %d" ,&n ,&m) && n + m)
   {
      for(i = 1 ;i <= n ;i ++)
      scanf("%d" ,&num[i]);
      while(m--)
      {
         scanf("%d" ,&q);
         memset(markc ,0 ,sizeof(markc));
         memset(markq ,0 ,sizeof(markq));
         int ss = 0;
         for(i = 1 ;i <= q ;i ++)
         {
            scanf("%d" ,&a);
            if(!markq[a]) ss ++;
            markq[a] = 1;
         }
         int L ,R ,nowsum ,Ans;
         L = 1 ,nowsum = 0 ,Ans = n;
         //找到LR
         for(i = 1 ;i <= n ;i ++)
         {
            if(markq[num[i]]) 
            {
               if(!markc[num[i]]) nowsum ++;
               markc[num[i]] ++;
               if(nowsum == ss) 
               {
                  R = i;
                  break;
               }
            }
         }
         Ans = R - L + 1; 
         for(i = L ;i <= n ;i ++)
         {
            if(markq[num[i]]) 
            if(!(--markc[num[i]]))
            {
               int ok = 0;
               for(int j = R + 1 ;j <= n ;j ++)
               {
                  if(markq[num[j]])
                  {
                     markc[num[j]] ++;
                     if(num[j] == num[i])
                     {
                        ok = 1;
                        R = j;
                        break;
                     }
                  }
               }
               if(!ok) break;
            }
            if(Ans > R - i) Ans = R - i;
         }
         printf("%d
" ,Ans);
      }
   }
   return 0;
}
      

原文地址:https://www.cnblogs.com/csnd/p/12062794.html