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