Problem - 7314
题目大意:有n个数组,从每个数组中取一个数构成数组b,求b中最大值和最小值的差的最小值
1<=n<=1e6;总数字数量<=1e6;-1e9<=数字大小<=1e9
思路:要想最大值和最大值的差最小,所以我们要对他们进行排序(前排提醒:1e6的排序在时间上非常极限,读写优化一定要有,常数尽可能小),越靠近的话差值就最小,我们给每个数字标上他们是第几个数组的,然后放在一个数组num里,按照数字的大小排序,然后我们要做的就是找到一个尽可能小的区间使其包含每一个数组中的数至少一个,我们建立l,r双指针,初始都指向0,用vis记录每个数组中的数出现的个数,cnt记录当前区间出现了几个数组中的数,在cnt=n之前,扩展区间右端点r,维护vis和cnt,cnt=n之后,再尝试缩小左端点l,直到cnt!=n,这时num[r-1]-num[l-1]即为满足题目要求的差值,在双指针移动的过程中维护此最小值即可
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int vis[N];
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin >> t;while (t--){int n;cin >> n;vector<pair<int, int>>num;//将数字都放在一个数组里便于排序for (int i = 1; i <= n; i++){int x;cin >> x;vis[i] = 0;for (int j = 1; j <= x; j++){int y;cin >> y;num.push_back(make_pair(y, i));//记录数组编号}}sort(num.begin(), num.end()); //按数值大小排序int len = num.size()-1;int r = 0, l = 0;int cnt = 0;int mi = 0x7fffffff; while(1){bool flag = 1;//还有没有符合条件的区间while (cnt != n && r <= len){//在找到合法区间前,扩大区间if (!vis[num[r].second]){ cnt++;//记录出现过几个数组的数}vis[num[r].second]++;r++;}if (cnt == n){flag = 0;while (cnt == n){//找到合法区间后,缩小区间直到不合法vis[num[l].second]--;if (vis[num[l].second] == 0){cnt--;}l++;if (l > len)break;}mi = min(mi, num[r - 1].first - num[l-1].first);//维护答案最小值} if (flag)break;}cout << mi << endl;}return 0;
}