• 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
    ",maxcount);
    	return 0;
    }
    


  • 相关阅读:
    特殊json处理
    css3
    居中定位
    微信支付
    vue 封装cookie,请求,登录拦截,接口拦截
    vue中axios的封装(简易版拦截,get,post
    JS的Event Loop
    JS模块化
    JS的排序算法
    时间复杂度 空间复杂度
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154061.html
Copyright © 2020-2023  润新知