zoukankan      html  css  js  c++  java
  • hdu 2158 最短区间版大家来找碴(尺取法)

    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
     
    题意:要求找出一个最短区间,该区间要包含这Q个整数数值。
    思路:尺取
    #include <cstdio>
    #include <map>
    #include <iostream>
    #include<cstring>
    #include<bits/stdc++.h>
    #define ll long long int
    #define M 6
    using namespace std;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
    int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    int n,m,q;
    int a[100007];        //询问数组 
    int temp[107];
    bool vis[100007]; //标记为需求数 
    int num[100007]; //需求数的数量 
    int main(){
        ios::sync_with_stdio(false);
        while(~scanf("%d%d",&n,&m)){
            if(!n&&!m) break;
            for(int i=1;i<=n;i++)
                scanf("%d",a+i);
            for(int i=1;i<=m;i++){
                memset(vis,0,sizeof(vis));
                memset(num,0,sizeof(num));
                scanf("%d",&q);
                int sum=0;
                for(int j=1;j<=q;j++){
                    scanf("%d",temp+j);
                    if(!vis[temp[j]]) vis[temp[j]]=1,sum++;
                }
                int ans=inf; int u,v,s;
                u=v=1;
                s=0;
                while(1){
                    while(v<=n&&s<sum){
                        if(vis[a[v]]&&!num[a[v]]) num[a[v]]++,s++; //如果是需求数且没出现则s++ 
                        else if(num[a[v]]) num[a[v]]++;//不然只记录下数目 
                        v++;
                    }
                    if(s<sum) break;
                    ans=min(ans,v-u);
                    if(vis[a[u]]&&num[a[u]]==1) num[a[u]]--,s--;    //与上面对应 
                    else if(num[a[u]]>1) num[a[u]]--;
                    u++;
                }
                cout<<ans<<endl;
            }
        }
    }
  • 相关阅读:
    Python爬虫之记录一次下载验证码的尝试
    Python之学会测试,让开发更加高效(一)
    NLP(二十八)多标签文本分类
    NLP(二十七)开放领域的三元组抽取的一次尝试
    NLP(二十六)限定领域的三元组抽取的一次尝试
    Numpy之数据保存与读取
    TortoiseGit的首次使用
    NLP(二十五)实现ALBERT+Bi-LSTM+CRF模型
    NLP(二十四)利用ALBERT实现命名实体识别
    NLP(二十三)序列标注算法评估模块seqeval的使用
  • 原文地址:https://www.cnblogs.com/wmj6/p/10386505.html
Copyright © 2011-2022 走看看