尺取法小计

尺取法简介

尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的。

那么,用”尺取法“做上面这道题思路应该是这样的:

其实,这种方法很类似于蚯蚓的蠕动。

1)用一对脚标 i , j i, j i,j。最开始都指向第一个元素。

2)如果区间 i i i j j j之和比 s s s小,就让 j j j往后挪一位,并把 s u m sum sum的值加上这个新元素。相当于蚯蚓的头向前伸了一下。

3)如果区间 i i i j j j之和比 s s s大,就让 s u m sum sum减掉第一个元素。相当于蚯蚓的尾巴向前缩了一下。

4)如果i到j之和刚好等于 s s s,则输入。

上一道题来熟悉一下

有一个长度为NN的正整数序列 ( 10 < N < 100 , 000 ) (10 < N < 100,000) (10<N<100,000),每一个数字都小于等于10000,再给定一个正整数 S ( S < 100 , 000 , 000 ) S (S < 100,000,000) S(S<100,000,000),试求一个连续子序列,使得该序列的数字之和大于或等于 S S S,并且要求该子序列尽量短。

tips1:这道题首先需要想到的是使用 s u m [ i ] sum[i] sum[i]数组表示前 i i i个元素的和,对于这种求序列和的问题,很多时候都会使用到这种数组。

暴力–代码不一定对

最简单的方法,二重循环遍历

		for (ll i = 1; i <= n; i++) {
			for (ll j = i + 1; j <= n; j++) {
				if (sum[j] - sum[i] >= s)
					ans = min(ans, j - i);
			}
		}

显然暴力过于low,如果提交肯定会TLE,想一个办法改进一下。

二分搜索

二分搜索简介,根据简介的内容,我们只需要
1)将子序列的长度作为搜索的对象
2)对二分搜索的每个 m i d mid mid值,判断该长度的子序列能否满足和大于 S S S
3)由于是求最短长度,如果子序列满足条件,那么 r = m i d r=mid r=mid,否则 l = m i d l=mid l=mid
直接使用STL的 l o w e r _ b o u n d lower\_bound lower_bound函数代码将更加简洁.
在这里插入图片描述

最后介绍尺取法

尺取法通常会用于处理区间问题,

1、什么时候可以用尺取法?

尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,比如单调性的区间就是经常用到尺取法的经典区间。

2、用尺取法的时候要注意什么问题?

1、 什么情况下能使用尺取法?

2、如何推进区间的端点?

3、如何利用当前区间更新结果值?

4、何时结束区间的枚举?

对于该题而言,我们依次回答上面四个问题
1、虽然对原数组而言并不具有什么单调性,但是 s u m sum sum数组却具有单调性。而具有单调性的数组一般是适用尺取法的。

2、对每个左端点,给一个 w h i l e while while循环,只要有 s u m < S sum<S sum<S,就不断的将右端点右移。

3、循环结束后,如果 s u m [ r ] − s u m [ l ] > s sum[r]-sum[l]>s sum[r]sum[l]>s,说明 r − l r-l rl可以被用于更新

4、如果(2)中直到循环结束的 s u m [ r ] − s u m [ l ] sum[r]-sum[l] sum[r]sum[l]值也不能够满足要求,此时就可以break了,因为左端点右移得到 s u m [ r ] − s u m [ l ] sum[r]-sum[l] sum[r]sum[l]值只会更小、

s = 15 s=15 s=15,给定数据15 5 1 3 5 10 7 4 9 2 8,区间变化如下
在这里插入图片描述

再来一道题

在这里插入图片描述
该问题也就是求一个最小的区间,改区间的数字覆盖所有数字的种类。
1)首先对每一个左端点 s s s,一个 w h i l e while while循环,求出能使得 s − − t s--t st的知识点全覆盖的最小的右端点 t t t,如果该 s s s,不能有一个 t t t使得 s − − t s--t st覆盖所有知识点,就可以退出循环了。
2)如果可以完全覆盖,那么可以比较 s − t s-t st的值是否比之前的answer更小,更新结果值。右移 s s s一位,将 s s s对应的知识点-1。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值