ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有N个,分为K种。简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。 小布生日快到了,于是小西打算剪一段彩带送给小布。为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠。同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差。

Input

第一行包含两个整数N, K,分别表示彩珠的总数以及种类数。接下来K行,每行第一个数为Ti,表示第i种彩珠的数目。接下来按升序给出Ti个非负整数,为这Ti个彩珠分别出现的位置。

Output

应包含一行,为最短彩带长度。

对彩珠排序

用一个数组记录当前区间每种颜色出现次数

从左到右扫描结束位置,若得到合法结束位置则尽量右移起始位置,计算长度若更优则更新答案,起始位置右移一,重复本步

#include<cstdio>
#include<algorithm>
inline int read(){
    int x=0,c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
int ts[64],t=0,ans=2147483647;
struct p{
    int x,t;
}ps[1000005];
int pp=0;
inline bool operator<(p a,p b){return a.x<b.x;}
int n,k,m,x;
int main(){
    n=read();k=read();
    for(int i=1;i<=k;i++){
        m=read();
        while(m--){
            x=read();
            ps[pp++]=(p){x,i};
        }
    }
    std::sort(ps,ps+pp);
    int l=0,r=0;
    while(1){
        while(t<k&&r<=n){
            if(!ts[ps[r++].t]++)t++;
        }
        if(r>n)break;
        while(1){
            if(!--ts[ps[l++].t]){
                int v=ps[r-1].x-ps[l-1].x;
                if(v<ans)ans=v;
                t--;
                break;
            }
        }
    }
    printf("%d",ans);
    return 0;
}

 

posted on 2016-02-26 14:13  nul  阅读(410)  评论(0编辑  收藏  举报