来源:牛客网:

时间限制: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;
}