PAT乙级1030

尺取法

尺取法通常是指对数组保存一对下表(起点,终点),然后根据实际情况交替推进两个端点直接得出答案的方法,这种操作很像是尺蠖(日文中称为尺取虫)爬行的方式故得名。

(以上文字摘自挑战程序设计竞赛第2版)

Codeforces中显示它的算法名称叫做"two pointers". 直译成中文的话叫双指针法. 怎么说呢……做到提高组之后,很多oier仅仅是觉得好像有这么一个两个指针从左到右扫一遍的算法存在,却不知道它的名字.(其实是因为大佬们根本没把它当个算法) 这个算法不是很难,却很有意思. 尺取法是一种比较基础的算法,一般用来解决具有单调性的区间问题. 当然,说到单调性,大家都会想到二分. 尺取法能做的题,有很大的概率也可以用二分解决,不过尺取和二分的复杂度在不同的题目中往往是不同的. 所以尺取法的题大概也是找到可二分性然后优化之. 我想不到类比尺取法的实际问题,所以我只能给了很多例题. 大家如果有的话可以告诉我,我将非常感谢. 维护两个指针 l,r ,每次确定区间的左端点,让 r 不断向右移动,直到满足条件停下,维护一下答案,直到 r>n 或者其它情况(视题目而定). 而实际中很多算法都要用到尺取法来辅助或者优化计算,尤其是分治算法.

(摘自洛谷日报第73期,原文章链接:https://baijiahao.baidu.com/s?id=1615129382322508344&wfr=spider&for=pc,原文作者:Fuko_Ibuki)

这个题目先对数组进行排序,这个问题就成为了具有单调性的区间问题,定义两个指针head,tail,tail取便所有数组,判断a[head]<=p*a[tail](不难发现,此时a[head]是完美数列中的最小值,a[tail]是最大值),符合条件就更新最大长度,如果不符合就让头指针++

参考sxy大佬的代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long a[100001];

int main()
{
	int n,p,i;
	cin>>n>>p;
	for(i=0;i<n;i++) cin>>a[i];
	sort(a,a+n);
	int head=0,tail=0,ans=1;
	while(tail<n-1)
	{
		while(a[tail]<=p*a[head]&&tail<=n-1)
		{
			ans=max(ans,tail-head+1);
			++tail;
		}
		while(a[tail]>p*a[head])
		++head;
	}
	cout<<ans;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值