传送门
题目大意:
给出 n n n天,每天有若干件衣服,可以任选 m m m天然后每天选出一件衣服,问如何选择使得选取的 m m m件衣服中最大最小值的差值最小
思路:
如果我们不考虑天数,直接按权值排序,然后对于每个左边界,我们要找的就是恰好的第一个右边界使得这个区间内含有 m m m种衣服,这个区间显然是可变化的。这个问题很明显就是经典的尺取问题啊(比赛时傻逼了想到开头却没想到尺取),我们只需要维护一个两个指针并用数组记录衣服的种类个数
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e6+10;
struct node{
int w,id;
bool operator < (const node &p) const {
return w<p.w;
}
}a[maxn];
int b[maxn];
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,m,cnt=0;
scanf("%d%d",&n,&m);
for(int i=1,x,w;i<=n;i++){
scanf("%d",&x);
for(int j=0;j<x;j++){
scanf("%d",&w);
a[cnt++]={w,i};
}
}
sort(a,a+cnt);
int l=0,r=0,num=0;
int ans=inf;
//for(int i=0;i
while(l<cnt){
while(r<cnt && num<m){
if(!b[a[r].id]) num++;
b[a[r].id]++;
r++;
}
if(num<m) break;
ans=min(ans,a[r-1].w-a[l].w);
if(--b[a[l].id]==0) num--;
l++;
}
printf("%d\n",ans);
return 0;
}