原题
题目描述
有
天,每天穿一件衣服,第 i 天有
j$件衣服的的权值为
。从
天中选择
天,求这
天中,所穿衣服的权值最大与最小值的最小差是多少。
样例
输入
4 3
1 3
2 8 6
1 2
3 1 7 5
输出
2
思路
因为数据比较多,所以我们考虑一些必要的条件
衣服的权值。
这是第几天要穿的衣服。
所以我们可以开结构体存储,输入时标记天数。
然后就用滑动窗口划过去即可
- 按照权值的大小排序。
- 找到前 件衣服包含 个不同的天。
- 然后在滑动过程中更新
最大的权值 最小的权值。
因为之前已经排过序了,所以最大的权值就是右端点的权值,最小的权值就是左端点的权值。 - 每右移左端点,就往右端点搜,更新右端点,直到搜到另一个包含 个不同天的区间为止,右端点就是这个区间的右端点。
- 重复上述搜索即可,直至搜索到 。
- 答案就是
。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+6;
struct node{int day,v;}a[maxn];
bool cmp(node x,node y){return x.v<y.v;}
int n,m,k,l=1,r,tmp,sum,ans=1e9;
bool vis[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
for(int j=1;j<=k;j++)scanf("%d",&a[++sum].v),a[sum].day=i;
//标记天数
}
sort(a+1,a+sum+1,cmp);//排序
while(tmp<m)//找到前tmp件衣服包含m个不同的天
{
r++;
if(!vis[a[r].day])vis[a[r].day]=1,tmp++;
}
while(r<=sum)//滑动
{
ans=min(ans,a[r].v-a[l].v);vis[a[l].day]=0;tmp--;l++;
if(!vis[a[l].day])vis[a[l].day]=1,tmp++;
while(tmp<m&&r<=sum)
{
r++;
if(!vis[a[r].day])vis[a[r].day]=1,tmp++;
}
}
printf("%d\n",ans);
}