PAT1020 完美数列 有点意思

要点:题目要求一个数,这个数的范围是1~n,故可以采用二分查找这个数。

1.假设现在这个数是k,即可以选择K个数可以用它们组成一个完美数列。我们做出这个判断的依据是题目中的条件,故只有这k个数中的最大最小值是要关心的。
2.现在将输入的序列由小到大排列,而1中所用到的这个最大值最大可以是序列的最后一个元素,若用数组存储的话便为data[n-1];最小只能是data[k-1],这里的k指的是选的数。
3.选好最大值后便找能作为这k个数的最小值进行验证,可以知道下标从0~i-mid+1的数都可以作为最小值,其中的i为最大值的下标。
故代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
const int maxn = 1e5+10;
typedef long long int ll;
ll p,data[maxn];
int n;
int main()
{
    
    
    int i,flag,j;
    cin>>n>>p;
    for(i=0;i<n;i++)
        cin>>data[i];
    sort(data,data+n);
    int left = 1,right = n,mid,_max = 0;
    while(left<=right)
    {
    
    
        flag = 0;
        mid = (left+right)/2;
        for(i=n-1;i>=mid-1;i--)
        {
    
    
            for(j=i-mid+1;j>=0;j--)
            {
    
    
                if(data[i] <= data[j] * p)
                {
    
    
                    flag = 1;
                    break;
                }
            }
            if(flag == 1)
                break;
        }

        if(flag == 1)
        {
    
    
            left = mid + 1;
            if(_max < mid)
                _max = mid;
        }else
            right = mid - 1;
    }
    cout<<_max;
    return 0;
}

然而超时了,不难看出其实没必要从下标0~i-mid+1的数据挨个检查,因为在检查这个最小值时最大值是确定的,p也是确定的,故检查最大的那个数即可,即下标为i-mid+1的那个数。若此数不满足那其他的更不满足了。
改进后:

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
typedef long long int ll;
ll p,data[maxn];
int n;
int main()
{
    
    
    int i,flag,j;
    cin>>n>>p;
    for(i=0;i<n;i++)
        cin>>data[i];
    sort(data,data+n);
    int left = 1,right = n,mid,_max = 0;
    while(left<=right)
    {
    
    
        flag = 0;
        mid = (left+right)/2;
        for(i=n-1;i>=mid-1;i--)
        {
    
    
            if(data[i] <= data[i-mid+1] * p)
            {
    
    
                flag = 1;
                break;
            }
        }

        if(flag == 1)
        {
    
    
            left = mid + 1;
            if(_max < mid)
                _max = mid;
        }else
            right = mid - 1;
    }
    cout<<_max;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44142774/article/details/114029188
今日推荐