来源:牛客网:

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

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

输入描述:
第一行包含两个整数N, K,分别表示彩珠的总数以及种类数。
接下来K行,每行第一个数为Ti,表示第i种彩珠的数目。接下来按升序给出Ti个非负整数,为这Ti个彩珠分别出现的位置。
输出描述:
应包含一行,为最短彩带长度。
示例1
输入
复制

6 3
1 5
2 1 7
3 1 3 8

输出
复制

3

备注:
在这里插入图片描述

题解:

双指针,尺取法
先固定左界为1,然后移动右界,当范围内达到要求的彩珠数量时,固定右届开始移动左界,直到范围内不再包含所有颜色的彩珠,不断更新最小范围
详细可以看代码
不过代码有错误。。。我还没发现。。。。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1100045;
struct node{
    ll col;//颜色 
    ll xy;//坐标 
    bool operator <(const node tmp)const{
        return this->xy<tmp.xy;
    }
}a[maxn];
long long cnt[maxn];
signed main()
{
    ll n,k;
    cin>>n>>k;
    ll ant=0;
    for(int i=1;i<=k;i++)
    {
        ll x;
        cin>>x;
        for(int i=1;i<=x;i++)
        {
            int y;
            cin>>y;
            a[++ant].col=i;
            a[ant].xy=y;
        }
    }
    sort(a+1,a+1+ant);
    ll l=1,r=maxn;
    ll sum=1e9+10;
    ll tmp;
    ll res=0;//所选不同颜色彩珠的数量 
    for(int i=1;i<=ant;i++)//从头开始枚举每一个彩珠 
    {
        if(cnt[a[i].col]==0)//说明这个颜色还么选
        res++; 

        cnt[a[i].col]++;//加上当前彩珠

        while(res==k)//当数量足够时 
        {
            tmp=a[i].xy-a[l].xy; 
            sum=min(sum,tmp);//记录最小距离 

            //-------接下来开始缩小范围
            //左边界开始向右靠,缩小边界
            cnt[a[l].col]--;//将左边界l的彩珠去掉 
            if(cnt[a[l].col]==0)res--; 
            l++;//向右靠 
        } 

    }
    cout<<sum<<endl;
    return 0;
}