原题
题目描述
有
n
n
n天,每天穿一件衣服,第 i 天有
k
i
k_i
ki 件衣服可以穿,穿第
j
j
j件衣服的的权值为
a
i
j
a_{ij}
aij 。从
n
n
n天中选择
m
m
m天,求这
m
m
m天中,所穿衣服的权值最大与最小值的最小差是多少。
样例
输入
4 3
1 3
2 8 6
1 2
3 1 7 5
输出
2
思路
因为数据比较多,所以我们考虑一些必要的条件
:
:
:
1
、
1、
1、衣服的权值。
2
、
2、
2、这是第几天要穿的衣服。
所以我们可以开结构体存储,输入时标记天数。
然后就用滑动窗口划过去即可
:
:
:
- 按照权值的大小排序。
- 找到前 t m p tmp tmp件衣服包含 m m m个不同的天。
- 然后在滑动过程中更新
a
n
s
:
ans:
ans:
a n s = ans= ans=最大的权值 − - −最小的权值。
因为之前已经排过序了,所以最大的权值就是右端点的权值,最小的权值就是左端点的权值。 - 每右移左端点,就往右端点搜,更新右端点,直到搜到另一个包含 m m m个不同天的区间为止,右端点就是这个区间的右端点。
- 重复上述搜索即可,直至搜索到 n n n。
- 答案就是
a
n
s
ans
ans。
代码
#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);
}