【Blue Bridge Cup】Chocolate (two points)

Resource limit
Time limit: 1.0s Memory limit: 256.0MB
Problem description
There are K children visiting Xiaoming's house on Children's Day. Xiao Ming took out a collection of chocolates to entertain the children.
Xiao Ming has a total of N pieces of chocolate, of which the i-th piece is a rectangle composed of Hi x Wi squares.

To be fair, Xiao Ming needs to cut out K pieces of chocolate from these N pieces of chocolate and distribute them to the children. The cut chocolate needs to meet:

  1. The shape is a square and the side lengths are integers
  2. same size

For example, a 6x5 chocolate can be cut into 6 2x2 chocolates or 2 3x3 chocolates.
Of course, the children all want the chocolate to be as large as possible. Can you help Xiao Hi calculate the maximum side length?
Input format
  The first line contains two integers N and K. (1 <= N, K <= 100000)
  Each of the following N lines contains two integers Hi and Wi. (1 <= Hi, Wi <= 100000)
  The input guarantees that each child will get at least one 1x1 chocolate.
Output Format
  Output the maximum possible side length of the cut square chocolate.
  
Sample input
2 10
6 5
5 6
Sample output
2
Data scale and convention
  Peak memory consumption (including virtual machine) < 256M
  CPU consumption < 1000ms

Please output strictly according to the requirements, and do not superficially print superfluous content like: "Please enter...".

Note: The
  main function needs to return 0;
  only use the ANSI C/ANSI C++ standard;
  do not call special functions that depend on the compilation environment or operating system.
  All dependent functions must be explicitly #included in the source file
  . Common header files cannot be omitted through project settings.

When submitting your program, take care to select the desired language type and compiler type.

Thought analysis

The meaning of the question is that given N rectangles of known length and height, K squares are to be cut out of the rectangles. The side length x of the square is required, and x is as large as possible under the condition that K pieces of the rectangle can be cut out.

First of all, according to the analysis of time complexity, the algorithm that can be used can only be in O(n) and O(nlgn). Then note that it xshould be as large as possible, and you can think of binary enumeration x to the right boundary. The time complexity of the
binary enumeration is O(lgn), we can only find out how many squares the rectangle can cut out by the side length x of the current enumeration through O(n). xA little observation of the sample can be found: the height of a rectangle is H and the width is W, and this rectangle can cut out (W/x)*(H/x)a square at most.
Therefore, we create a rectangular array. For each enumerated x, O(n) traverses the rectangular array, accumulates the maximum number of squares cut out of all rectangles , and compares cntit with the target number .k

  1. If cnt < xit is proved that the x value of the current enumeration is larger than the x value required by k, the right boundary pointer needs to be moved to the left
  2. If cnt > xit is proved that the x value of the current enumeration is smaller than the x value required by k, the left boundary pointer needs to be moved to the right
  3. If cnt==xwe still need to move the left border to the right, make sure x is as large as possible

Explanation for case 3:

x 1 2 3 4 5
k 4 2 2 2 1

Such examples are possible. x can make k=2 at 2, 3, and 4, so we need to take the right boundary x=4.

#include <iostream>
#include <vector>
using namespace std;

struct node{
    
    
	int x, y;
};

vector<node> arr;

int main()
{
    
    
	int n, k, x;
	scanf("%d%d",&n,&k);
	while(n--)
	{
    
    
		node t;
		scanf("%d%d",&t.x,&t.y);
		arr.push_back(t);
	}
	int l = 1, r = 100010; //枚举的区间为[l,r) 
	while(l < r)
	{
    
    
		int mid = (l+r)/2; //枚举边长 
		int cnt = 0; //所有矩形能切出边长mid正方形的个数 
		for(int i = 0;i < arr.size();i++)
		{
    
    
			node t = arr[i];
			if(t.x >= mid && t.y >= mid) cnt += (t.x/mid)*(t.y/mid);
		}
		if(cnt < k) //能切的正方形数小于k,证明mid取值大了,需要缩小右边界 
		{
    
    
			r = mid;
		} 
		else //能切的正方形数大于k,证明mid取小了,需要扩大左边界。当cnt==k时也要扩大左边界,因为要取mid最大值 
		{
    
    
			l = mid+1;
		}
	}
//	int cnt = 0, ans = l;
//	for(int i = 0;i < arr.size();i++)
//	{
    
    
//		node t = arr[i];
//		if(t.x >= l && t.y >= l) cnt += (t.x/l)*(t.y/l);
//	}
//	if(cnt < k) ans = l-1;
	printf("%d\n",ans-1);
	return 0; 
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325660605&siteId=291194637