描述
给定N个数组,每个数组都包含M个整数。
现在你被要求从每个数组中选出一个数,总共N个数,然后求出其中最大与最小的差值。
在MN种选法中,差值最小是多少?
输入
第一行包含两个整数N和M。
以下N行,每行包含M个整数。
对于50%的数据,1 ≤ N × M ≤ 10000
对于100%的数据,1 ≤ N × M ≤ 200000 0 ≤ 每个整数 ≤ 1000000
输出
最小的差值
样例输入
3 3
8 1 6
3 5 7
4 9 2
样例输出
2
思路
给了一个n*m
的矩阵,要从每一行选出一个数,使得选出来的数中的最大值与最小值的差值最小。
可以用尺取法来考虑这个问题,首先对整个矩阵中的数字从小到大排序,并且记录一下当前数字在第几行,然后从左到右扫描。用一个标记数组来记录当前选中的数字的个数,记录一下当前选中某一行的最大的数,当选中的数到达行数时证明已经从每一行选出了一个数,这时候记录一下最大值与最小值的差,刷新一下最小值.
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pir;
const int inf=1e9+7;
const int N=2e5+20;
int cnt[N];
int main()
{
vector<pir>v;
int n,m,num;
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
cin>>num;
v.push_back(make_pair(num,i));
}
sort(v.begin(),v.end());
int ans=inf,tmp=0,p=0;
for(int i=0; i<v.size(); i++)
{
while(p!=v.size()&&tmp<n)
{
int x=v[p].second;
cnt[x]++;
if(cnt[x]==1)
tmp++;
p++;
}
if(tmp==n)
ans=min(ans,v[p-1].first-v[i].first);
int x=v[i].second;
cnt[x]--;
if(cnt[x]==0)
tmp--;
}
cout<<ans<<endl;
return 0;
}