思路
由于分出来的每块巧克力相同,故只要某个边长的划分方法满足条件,则小于该边长的划分方法一定满足条件$\Rightarrow$单调性
$\Rightarrow$二分
。存储每块巧克力的边长时,有意识地将其按最短边最长边的顺序排序,最小的划分边长为1,最大的划分边长为所有巧克力中的最长边,对于每种划分情况,判断函数中遍历一遍所有巧克力,然后比较总共能划分的块数是否大于小孩人数即可。
注意
1.最大的划分边长是所有巧克力中的最长边而非所有巧克力中的最短边
,因为不是所有巧克力都要进行划分,只要已划分的巧克力分出的块数满足条件即可不再划分其他巧克力,故最大划分边长应取大
2.对于每一种边长划分情况,对应到每一块巧克力上,能得到的划分块数为(s[i].w / length) * (s[i].h / length)
(都是下取整,可以理解成将长和宽分别划分后的组合)
3.本题的二分可以理解成找满足性质的最大(最后)的一个元素
,故采用第一个二分模版(l=mid)
代码
#include <bits/stdc++.h>
using namespace std;
int N, K;
struct S
{
int h;
int w;
bool operator<(const S &a) const
{
if (a.h != h)
return h < a.h;
else
return w < a.w;
}
} s[(int)1e5 + 10];
bool check(int length)
{
int cnt = 0;
for (int i = 0; i < N; i++)
{
cnt = cnt + (s[i].w / length) * (s[i].h / length);
if (cnt >= K)
return true;
}
return false;
}
int main()
{
scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++)
{
int h, w;
scanf("%d %d", &h, &w);
s[i].h = min(h, w);
s[i].w = max(h, w);
}
sort(s, s + N);
int l = 1, r = s[N-1].w;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
printf("%d\n", l);
return 0;
}