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
C≤N≤5∗105,0 <
P
i
≤
1
0
9
P_i \le 10^9
Pi≤109
思路:
我们可以采用二分的思路,当然为了二分,肯定要让数组为单调性。所以我们将数组做一遍升序排序.
我们用二分枚举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;
}