D e s c r i p t i o n Description Description
给出 N N N 个数,我们需要选择其中的 R × C R \times C R×C 个数,,把它们填入一个 R × C R \times C R×C 的矩阵( R R R 行 C C C 列)中。
我们先定义一个函数 D ( i ) D(i) D(i) 代表第 i i i 行中最大的数和最小的数之差。对于整个矩阵,定义 F F F 为矩阵中 D ( i ) ( 1 ≤ i ≤ R ) D(i)(1\le i\le R) D(i)(1≤i≤R)的最大值。
我们需要 F F F 的值最少,你能求出最少可能达到的 F F F 值是多少吗?
I n p u t Input Input
第一行给出 3 3 3 个整数 N , R , C N,R,C N,R,C,对应题目中描述的参数。
接下来一行有 N N N 个整数,代表 N N N 个可以选择的数 P i P_i Pi。
O u t p u t Output Output
输出一行表示最少可能达到的 F F F 值
S a m p l e Sample Sample I n p u t Input Input
7 2 3
170 205 225 190 260 225 160
S a m p l e Sample Sample O u t p u t Output Output
30
H i n t Hint Hint
对于 50 % 50\% 50% 的数据, 1 ≤ N ≤ 1000 1\le N\le 1000 1≤N≤1000
对于所有数据, 1 ≤ R , C ≤ 1 0 4 , R × C ≤ N ≤ 5 ∗ 1 0 5 , 0 < P i ≤ 1 0 9 1\le R,C\le 10^4,R\times C\le N\le 5*10^5,0 < P_i \le 10^9 1≤R,C≤104,R×C≤N≤5∗105,0<Pi≤109。
T r a i n Train Train o f of of T h o u g h t Thought Thought
最大值最小
那就是二分了
我们先二分一个答案
然后贪心判断能否填R行
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int A[500005], S[500005];
int n, r, c;
int Check(int k)//判断最小值为k是否可行
{
int t = 0;
for(int i = 1; i <= n - c + 1; ++i)
if(S[i] <= k)t++, i += c - 1;
return t >= r;
}
int main()
{
scanf("%d%d%d", &n, &r, &c);
for(int i = 1; i <= n; ++i)
scanf("%d", &A[i]);
sort(A + 1, A + n + 1);
for(int i = 1; i <= n - c + 1; ++i)
S[i] = A[i + c - 1] - A[i];//算i到i+c-1的最大差
int left = 0, right = 1e9;
while(left < right)
{
int mid = (left + right) / 2;
if(Check(mid))right = mid;
else left = mid + 1;
}
printf("%d", right);
return 0;
}