尺取法

尺取法的整个过程分为4部:

1.初始化左右端点

2.不断扩大右端点,直到满足条件

3.如果第二步中无法满足条件,则终止,否则更新结果

4.将左端点扩大1,然后回到第二步

返回的推进区间开头和结尾,求满足条件的最小区间的方法称为尺取法。

参考博客:尺取法枚举区间
:尺取法 — 详解 + 例题模板(全)

例:Poj3061

题意:给定一个序列,使得其和大于或等于S,求最短的子序列长度。

分析:首先,序列都是正数,如果一个区间其和大于等于S了,那么不需要在向后推进右端点了,因为其和也肯定大于等于S但长度更长,所以,当区间和小于S时右端点向右移动,和大于等于S时,左端点向右移动以进一步找到最短的区间,如果右端点移动到区间末尾其和还不大于等于S,结束区间的枚举。

这个题目区间和明显是有趋势的:单调变化,所以根据题目要求很容易求解,但是在使用之间需要对区间前缀和进行预处理计算。

代码:


#include   
#include   
#include   
#define MAX 100005  
#define LL long long  
#define INF 0x3f3f3f3f  
  
using namespace std;  
LL a[100010];  
int n, t, ans = INF;  
LL sum, s;  
  
int main()  
{  
    scanf("%d", &t);  
    while (t--){  
        scanf("%d %I64d", &n, &s);  
        for (int i = 0; i < n; i++) scanf("%I64d", a+i);  
        int st = 0, en = 0;  
        ans = INF; sum = 0;  
        while (1){  
            while (en<n && sum<s) sum += a[en++];  
            if (sum < s) break;  
            ans = min(ans, en-st);  
            sum -= a[st++];  
        }  
        if (ans == INF) ans = 0;  
        printf("%d\n", ans);  
    }  
    return 0;  
}

你可能感兴趣的:(板子)