尺取法

    尺取法一般用来求解最大/最小区间问题。用两个指针代表区间的首尾,反复地推进区间的开头和末尾,来求取满足条件的最小/大区间,复杂度为O(n)。

       当一个区间满足条件时,左指针推进,判断新区建是否满足条件,如果不满足条件,那么区间末尾向后扩展,直到满足条件为止。这样在区间推移过程中我们就得到了很多满足条件的区间,根据题意取最优即可。

    当满足以下条件时,可以使用尺取法:若从开始,至少要到才能满足条件,即:最初满足条件的区间为,则从开始的最初满足条件的区间为,必然有t≤t'。

例题: poj3061 Subsequence

       设若从开始总和最初不小于s时的连续子序列为,这时,所以从开始总和最初大于s的连续子序列如果是的话,则必然有t≤t'。所以可以用尺取法。

(1)以s = 0,t = 0,sum = 0初始化;

(2)只要依然有sum < S,就不断将sum累加,并将t加1;

(3)如果(2)中无法满足sum >= S则终止,否则更新res = min(res, t - s + 1);

(4)将sum减去,s增加1然后回到(2)。

由于t最多变化t次,故算法复杂度为O(n)。

代码如下:

#include <cstdio>
using namespace std;
#define N 100005
#define min(a, b) (a) < (b) ? (a) : (b)
int a[N], sum[N];

int main(){
	int tc, n, s;
	scanf("%d", &tc);
	while(tc --){
		scanf("%d %d", &n, &s);
		sum[0] = 0;
		for(int i = 1; i <= n; ++i)
			scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i];
		int beg = 1, en = 1, ans = N;
		while(en <= n){
			int tmp = sum[en] - sum[beg - 1];
			if(tmp >= s)
				ans = min(ans, en - beg + 1), ++beg;
			else
				++en;
		}
		printf("%d\n", ans == N ? 0 : ans);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值