PTA | 1030 完美数列 分数 25 知识点:双指针 找规律

253 阅读1分钟

PTA | 程序设计类实验辅助教学平台 (pintia.cn)

这道题的意思是什么呢?举个例子

例子1

首先我们把给定的数组排个序,然后我们拿每个数x×px×p,看是否x×p>MAXx×p>MAX,我们发现除了1×p<MAX1×p<MAX2×p<MAX2×p<MAX外其余的数都满足条件,因此满足条件的个数是8

image.png

例子2

在举个例子,把20改为10,此时数组中最大值就是10:

我们发现除了1×p1×p小于MAX外,其余的元素都满足x×p>MAXx×p>MAX,因此答案是9 image.png

那么这道题应该怎么去做呢?

首先我们可以通过两个指针去枚举区间的端点,比如刚开始是这样的:

image.png

此时这个区间只有1个数,最大值是1,最小值是1。

a[j]×p > a[i]
1×8 >  1
最小值 × p > 最大值
满足条件  此时i++,跳到下一个点

一直到i为8的时候,此时是满足条件的最后一个值 image.png

这个时候让i不再走了,让j++。

当j走到2的时候我们发现不满足条件走到 3的时候我们发现 3×8>8 ,刚好满足条件。此时我们就可以求一下i,j之间的距离:

image.png

这个时候我们i没有走到尽头,i继续走:

image.png

image.png

最后我们发现[3,20]是最长完美子序列。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long LL;
LL a[N];
int main()
{
    int n,p;cin>>n>>p;
    
    for(int i=0;i<n;i++)cin>>a[i];
    sort(a,a+n);
    
    int ans=0;
    for(int i=0,j=0;i<n;i++)
    {
        
        while(a[j]*p<a[i])j++;
        
        ans=max(ans,i-j+1);
    }
    
    cout<<ans<<endl;
    return 0;
}