• A1085. Perfect Sequence


    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

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 long long num[100001];
     6 bool cmp(long long a, long long b){
     7     return  a < b;
     8 }
     9 int binSearch(long long num[], int low, int high, long long m, long long p){
    10     long long ans = p * m;
    11     int mid = high;
    12     while(low < high){
    13         mid = (low + high) / 2;
    14         if(num[mid] > ans){
    15             high = mid;
    16         }else low = mid + 1;
    17     }
    18     return low;
    19 }
    20 int main(){
    21     int N, p, index, ans = -1;
    22     scanf("%d%d", &N, &p);
    23     for(int i = 0; i < N; i++)
    24         scanf("%lld", &num[i]); 
    25     sort(num, num + N, cmp); 
    26     for(int i = 0; i < N; i++){
    27         index = binSearch(num, i + 1, N, num[i], p);
    28         index--;
    29         if(index - i + 1 > ans){
    30             ans = index - i + 1;
    31         }
    32     }
    33     printf("%d", ans); 
    34     cin >> N;
    35     return 0;
    36 }
    View Code

    总结:

    1、题意:给出一个数列和一个数字p,求满足M <= mp 的最长子数列, M与m分别为最大最小值。先对原数列排序一下,对比条件,显然M越大、m越小可以得到的子数列长度越长。因此可以从排好序的数列的两端往中间搜索答案,但是如果暴力二重循环会出现超时。因此,只能从左端递增遍历m, 而右端的M改用二分搜索,将复杂度变为 n*logn。

    2、二分搜索M,目标是找到序列中尽可能靠右的且满足 M <= mp 的M, 即最后一个满足所给条件的M。这个可以转化为搜索第一个满足 M > mp 的num[i]。 则num[i - 1]即为最后一个满足M <= mp的M。

    3、本题还可以使用两点法做,即使用两个指针,一遍扫描。如果a[j] <= a[i]* p成立,那么在[i, j]之内的任意k,都有a[k] <= a[i] *p成立,基于这一点设置i、j两个指针,j先递增,发现不等式不成立之后,i再向前走一步,如此反复。双指针法不仅可以一头一尾,也可以在同方向使用。代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 long long num[100001];
     6 bool cmp(long long a, long long b){
     7     return  a < b;
     8 }
     9 
    10 int main(){
    11     int N, p, index, ans = -1;
    12     scanf("%d%d", &N, &p);
    13     for(int i = 0; i < N; i++)
    14         scanf("%lld", &num[i]); 
    15     sort(num, num + N, cmp); 
    16     int i = 0, j = 0;
    17     while(i < N && j < N){
    18         long long temp = num[j] - num[i] * p;
    19         if(temp <= 0){
    20             ans = max(ans, j - i);
    21             j++;
    22         }else{
    23             i++;
    24         }
    25     }
    26     printf("%d", ans + 1); 
    27     cin >> N;
    28     return 0;
    29 }
    View Code

    4、二分搜索:

    1)搜索满足某条件的元素。  

    int binSearch(int num[], int low, int high, int x){
        int mid;
        while(low <= high){ //当搜索区间为空时结束
            mid = low + (high - low) / 2;
            if(num[mid] == x)
                return mid;
            else if(num[mid] > x)
                high = mid - 1;
            else low = mid + 1;
        }    
        return -1;
    }

    2)搜索第一个满足某条件的元素,在这个情况下要注意,被排好序的序列一定是从左到右先不满足条件,然后满足;另外,传入的high = N时,在搜索不到满足条件的数时,会返回N(假想N位置有数字); 返回的是low而不是mid。

    /*返回第一个大于等于x的元素。num[N]数组应从小到大排序。
    如果传入的high = N,则当序列中所有元素都小于x时,会返回N */
    int binSearch(int num[], int low, int high, int x){
        int mid;
        while(low < high){  //当low == high时结束搜索
            mid = low + (high - low) / 2;
            if(num[mid] >= x)
                high = mid;  //mid有可能就是结果,所以区间上限不能漏掉mid
            else low = mid + 1;
        }    
        return low;  //返回low而不是mid
    }
  • 相关阅读:
    (面试题)抽象类和静态属性以及静态方法(2019年10月17日)
    抽象类和静态属性以及静态方法(2019年10月17日)
    (面试题)多态(2019年10月16日)
    多态(2019年10月16日)
    (面试题)封装和继承(2019年10月15日)
    封装和继承(2019年10月15日)
    武汉大学2009年数学分析试题解答
    武汉大学2010年数学分析试题解答
    武汉大学2011年数学分析试题解答
    武汉大学2007年数学分析试题解答
  • 原文地址:https://www.cnblogs.com/zhuqiwei-blog/p/8510549.html
Copyright © 2020-2023  润新知