题意:
给你k个集合,每个集合里有ci个数,在每个集合里各挑一个数,求挑的k个数里的最大值减去最小值的值最小
思路:
可以将题意转换为,挑的所有数的集合一共有n种,求挑的数的最大值最小值的差最小
那么我们可以将所有数进行从小到大排序,然后用双指针,当所指的区间内的数有n种集合时,用最左边的数减去最右边的数,找出所有满足区间内有n个集合的区间,将差值取最小就可以了
当区间符合条件时,会出现有多个数来自同一个集合的情况,那么我们只要保证最大值和最小值所在的集合分别选最大值和最小值就可以了,剩下的集合随便选一个在区间里的集合内的数即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef pair<int,int> pii;
pii a[N];//记录数和所在的集合编号
int st[N];//st[i]表示区间里有第i个集合里的数的个数
int n;
void sove(){
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++){
st[i]=0;
int num;
cin>>num;
while(num--){
int x;
cin>>x;
a[++cnt]={x,i};
}
}
std::sort(a+1,a+1+cnt);
int c=0,ans=2e9;
for(int l=1,r=1;r<=cnt;r++){
if(st[a[r].second ]==0){
c++;
}
st[a[r].second ]++;
while(c==n){
ans=min(ans,a[r].first -a[l].first );
if(--st[a[l].second ]==0)c--;
l++;
}
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(),cout.tie();
int t;
cin>>t;
while(t--){
sove();
}
return 0;
}