1085. Perfect Sequence (25) -二分查找

题目如下:

Given a sequence of positive integers and another positive integer p. The sequence is said to be a "perfect sequence" if M <= m * p where M and m are the maximum and minimum numbers in the sequence, respectively.

Now given a sequence and a parameter p, you are supposed to find from the sequence as many numbers as possible to form a perfect subsequence.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive integers N and p, where N (<= 105) is the number of integers in the sequence, and p (<= 109) is the parameter. In the second line there are N positive integers, each is no greater than 109.

Output Specification:

For each test case, print in one line the maximum number of integers that can be chosen to form a perfect subsequence.

Sample Input:
10 8
2 3 20 4 5 1 6 7 8 9
Sample Output:
8


题目要求从给定序列中选取子序列,使得序列的最小值m、最大值M满足:M≤m*p,其中p为一个给定的正整数,输出能找到的最长子序列长度。

这道题一个很自然的思路就是设立一个头指针cur1,尾指针cur2,将序列按照升序排列,让cur2从最后一个元素向前指,cur1遍历从第一个元素到cur2的位置,找到合适的m时停下,记录长度,这样会有一个case超时,解决方法是让cur1从前到后遍历,cur2采用二分查找。

如果找到的位置使得M<m*p,说明M还可以更大,可以继续查找右半部分;如果M>m*p,说明M偏大,应该去左半部分找更小的;如果M=m*p,说明找到了合适的位置。在查找结束后,记录长度即可。

这段代码参考了Yangsongtao1991。

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;

int main()
{
	int n,p;
	scanf("%d%d",&n,&p);
	vector<long> seq(n);
	for(int i = 0; i < n; i++)
		scanf("%ld",&seq[i]);
	sort(seq.begin(),seq.end());
	int maxcount = 0, down = 1;
	for(int i = 0; i < n; i++)
	{
		long mp = p * seq[i];
		if(mp >= seq[n-1]) // 如果最大的元素都≤m*p,则从当前位置到最后全部计数。
		{
			if(maxcount < n - i){
                maxcount = n - i;
			}
			break;
		}
		int up = n-1;
		while(up > down)
		{
		    // 二分查找,结束条件为上界≤下界,根据mid处的乘积判定。
		    // 现在是确定了m,要找M,如果找到的位置<mp,说明M可能可以更大,向右找;如果>mp,说明M偏大,向左找。
		    // 如果当前位置恰好满足,则说明已经找到了最长满足要求的位置。
			int mid = (up + down)/2;
			if(seq[mid] > mp)
				up = mid;
			else if(seq[mid] < mp)
				down = mid + 1;
			else
			{
				down = mid + 1;
				break;
			}
		}
		if(down - i > maxcount)
			maxcount = down - i;
	}
	printf("%d\n",maxcount);
	return 0;
}


你可能感兴趣的:(算法,二分查找,pat)