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; }