尺取法
用一个数组来记录颜色,先固定左边,右移右边的范围,如果满足条件,再把左边的范围缩小,来找出最小的区间

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#define ll long long
#define pi 3.1415927
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
#define _int __int128_t
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
    return f*x;
}
void print(int x)
{
    if(x < 0) {putchar('-');x = -x;}
    if(x/10) print(x/10);
    putchar(x%10+'0');
}
ll n,k,m,col[65];
struct node
{
    ll color,x;
    /* data */
}a[1000005];
bool cmp(node x, node y){
    return x.x<y.x;
}
ll check(){
    for(int i=1;i<=k;++i){
        if(col[i]==0)
            return 0;
    }
    return 1;
}
int main ()
{
    ll T,i,t,j,p,sum=0;
    cin>>n>>k;
    p=0;
    for(i=1;i<=k;++i){
        cin>>T;
        for(j=1;j<=T;++j){
            a[++p].x=read();
            a[p].color=i;
        }
    }
    sort(a+1,a+n+1,cmp);
    ll l=1,ans=inf;
    for(int i=1;i<=p;++i){
        col[a[i].color]++;
        if(check())
        {
            while (check())
            {
                col[a[l].color]--;
                l++;
            }
            l--;
            col[a[l].color]++;
            ans=min(ans,a[i].x-a[l].x);
        }
    }
    cout<<ans<<endl;

    return 0;
}