T145305 【2020.8.24NOIP模拟赛】选数排列

T145305 【2020.8.24NOIP模拟赛】选数排列

题目描述
给出 N 个数,我们需要选择其中的 R×C 个数,,把它们填入一个 R×C 的矩阵(R 行 C 列)中。

我们先定义一个函数 D(i) 代表第 i 行中最大的数和最小的数之差。对于整个矩阵,定义 F 为矩阵中 D(i)(1≤i≤R) 的最大值。

我们需要 F 的值最少,你能求出最少可能达到的 F 值是多少吗?

输入格式
第一行给出 3 个整数N,R,C,对应题目中描述的参数。
接下来一行有 N 个整数,代表 N 个可以选择的数 P_i

输出格式
输出一行表示最少可能达到的 FF 值。

输入输出样例
输入

7 2 3
170 205 225 190 260 225 160

输出

30

说明/提示
对于 50% 的数据:1≤N≤1000
对于所有数据,1 ≤ R , C ≤ \le R,C\le R,C 104,R × \times × C ≤ N ≤ 5 ∗ 1 0 5 C\le N\le5*10^5 CN5105,0 < P i ≤ 1 0 9 P_i \le 10^9 Pi109

思路:
我们可以采用二分的思路,当然为了二分,肯定要让数组为单调性。所以我们将数组做一遍升序排序.
我们用二分枚举f.
那么怎么判断是否可以呢
判断这个数是否小于这次二分求出的情况
判断对于f这个值可以搞成R行
这样就可以了

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=5e5+10;
ll n,r,c,a[N],ans,ht[N];
bool check(ll x)
{
    
    
    for (ll i=0;i<=c;i++) ht[i]=0;
    for (ll i=c;i<=n;i++)
    {
    
    
        ht[i]=ht[i-1];
        if (a[i]-a[i-c+1]<=x) ht[i]=ht[i-c]+1;
    }
    return ht[n]>=r?true:false;
}
int main()
{
    
    
	scanf("%lld%lld%lld",&n,&r,&c);
	for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
	sort(a+1,a+1+n);
	ll l=0,r=999999999;
	while(l<=r)
	{
    
    
		ll mid=(l+r)/2;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%lld",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/108200683
今日推荐