尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的
使用尺取法时应清楚以下四点:
1、 什么情况下能使用尺取法? 2、何时推进区间的端点? 3、如何推进区间的端点? 3、何时结束区间的枚举?
尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步
得到根据其端点得到,那么尺取法便是不可行的。首先,明确题目所需要求解的量之后,区间左右端点一般从最整个数组的起点开始,之后判断区间是否符合条件在根据实际情况变化区间的端点求解答案。
以下是几个经典的使用尺取法的例题,都是从挑战书上引用的。(尺取法通常会需要对某些量进行预处理,以便能在使用时快速地判断。)
1、 Poj3061
题意:给定一个序列,找出最短的子序列长度,使得其和大于或等于S。
分析:首先,序列都是正数,如果一个区间其和大于等于S了,那么不需要在向后推进右端点了,因为其和也肯定大于等于S但长度更长,所以,当区间和小于S时右端点向右移动,和大于等于S时,左端点向右移动以进一步找到最短的区间,如果右端点移动到区间末尾其和还不大于等于S,
结束区间的枚举。
这个题目区间和明显是有趋势的:单调变化,所以根据题目要求很容易求解,但是在使用之间需要对区间前缀和进行预处理计算。
2、 poj3320
题意:一本书有P页,每一页都一个知识点,求去最少的连续页数覆盖所有的知识点。
分析:和上面的题一样的思路,如果一个区间的子区间满足条件,那么在区间推进到该处时,右端点会固定,左端点会向右移动到其子区间,且其子区间会是更短的,只是需要存储所选取的区间的知识点的数量,那么使用map进行映射以快速判断是否所选取的页数是否覆盖了所有的
知识点。
总结:尺取法的模型便是这样:根据区间的特征交替推进左右端点求解问题,其高效的原因在于避免了大量的无效枚举,其区间枚举都是根据区间特征有方向的枚举,如果胡乱使用尺取法的话会使得枚举量减少,因而很大可能会错误,所以关键的一步是进行问题的分析!
【以上转载自https://blog.csdn.net/consciousman/article/details/52348439】
北京师范大学第十六届程序设计竞赛决赛-重现赛 D
https://www.nowcoder.com/acm/contest/117/D
题目大意:三个有序的数列,求abs【第三个数列某数C-第二个数列某数B】+abd【第二个数列数B-第一数列数A】的最小值
题目分析:由于是有序的数列,所以可以枚举第二个数列的数B,然后找另外两个数列数与B的最小差值。易知寻找数时,只需寻找离数B最近的两个数【一个大于B一个小于B】即可,而由于数列是有序的,所以可以使用两个指针,一个指针指向第一个数列的首元素,一个指向第三个数列的首元素,然后一点点移动,找到满足要求的数之后,移动第二个数列枚举的数,继续移动第一个指针和第二个指针,由分析可知时间复杂度为O(N),其中找数的过程正是使用了尺取法的思想,由于数列有序,所以只需一点点向前推进分别找符合第二个数列枚举值要求的值。以下为AC代码
原文地址:https://www.cnblogs.com/MekakuCityActor/p/8971779.html