准确的来说这个应该叫尺取法?
先对所有的点按$x$坐标进行排序
我们维护两个指针$l,r$,每一次令$r$不断右移直到所有颜色齐全,再不断右移$l$直到颜色数不足,那么此时$[l-1,r]$这个区间里的彩珠肯定能构成所有颜色,且不难发现不会有包含这一区间的方案比它更优
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf; 10 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} 11 inline int read(){ 12 #define num ch-'0' 13 char ch;bool flag=0;int res; 14 while(!isdigit(ch=getc())) 15 (ch=='-')&&(flag=true); 16 for(res=num;isdigit(ch=getc());res=res*10+num); 17 (flag)&&(res=-res); 18 #undef num 19 return res; 20 } 21 const int N=1e6+5; 22 struct node{ 23 int x,col; 24 inline bool operator <(const node &b)const 25 {return x<b.x;} 26 }a[N]; 27 int cnt[105],tot,n,k,res=inf; 28 inline void add(int i){if(++cnt[a[i].col]==1) ++tot;} 29 inline void del(int i){if(--cnt[a[i].col]==0) --tot;} 30 int main(){ 31 // freopen("testdata.in","r",stdin); 32 n=read(),k=read(); 33 for(int i=1;i<=k;++i){ 34 int x=read(); 35 for(int j=1;j<=x;++j) a[++tot].x=read(),a[tot].col=i; 36 } 37 tot=0,sort(a+1,a+1+n); 38 int l=1,r=0; 39 while(true){ 40 while(tot<k&&r<n) add(++r); 41 if(r==n&&tot<k) break; 42 while(tot==k&&l<=r) del(l++); 43 cmin(res,a[r].x-a[l-1].x); 44 } 45 printf("%d ",res); 46 return 0; 47 }