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

利用STL里面的pair容器,默认排序的性质,就可以不需要自己写一个自定义函数了。
因为宝石的种类很少,当我们每取一段范围时,我们暴力判断以下这个区间是否满足。
时间复杂度 O(nlogn+n*60) ?
双指针判断条件
如果这段区间的宝石满足 题目要求
那么我们r++,同时加上此位置的宝石数目。
如果满足了我们就l++,同时减去那个位置的宝石数目。

这里的区间5-8的区间长度是3,不是4 ,注意一下即可.
代码:

/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cstdio>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<cmath>
#include <math.h>
#include<algorithm>

//#define int long long
using namespace std;
const int maxn = 100;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
vector <pair<int,int> > v;
int visited[100];
int n,k;
bool check(){
    for(int i=1;i<=k;i++){
        if(visited[i]==0) return false;
    }
    return true;
}

signed main(){
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        int m;
        cin>>m;
        for(int j=0;j<m;j++){
            int x;
            scanf("%d",&x);
            v.push_back(make_pair(x,i));
        }
    }
    sort(v.begin(),v.end());
    int l=0,r=0;
    int ans=MaxN;
    //for(auto it:v) cout<<it.first<<" "<<it.second<<endl;
    visited[v[0].second]++;
    while(r<n){
        //cout<<l<<" "<<r<<endl;
        if(check()){
            ans=min(ans,v[r].first-v[l].first);
            visited[v[l].second]--;
            l++;
        }
        else{
            r++;
            visited[v[r].second]++;

        }
    }
    cout<<ans<<endl;
    return 0;
}