POJ: 3061-Subsequence (detailed explanation of the ruler method template)

Subsequence

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 18795 Accepted: 8043

Description

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

Sample Input

2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5

Sample Output

2
3


Problem solving experience:

  1. The meaning of the question is to give you n numbers, and ask you to choose a continuous interval whose sum is not less than s, and ask you what is the length of the shortest interval.
  2. The template question of the ruler method, the ruler method is very interesting, and it is also called the ruler to take the worm. This can be said to be very vivid. It can be regarded as a worm of a certain length crawling in a linear table, and the complexity is O(N). There are many ways to write the ruler. Different ways of writing have different complexity. Here are three ways of writing.
    • The first one is the bisection plus ruler method. First, a length is divided into two parts, and then the ruler extraction method is used to test the sum of this bisection in the array. The complexity is O(NlogN).
    • The second feeling has little to do with taking the ruler. It uses dichotomy. First find the prefix sum, starting with each prefix sum, and the current prefix sum +s as the end point. Because the prefix sum is an increasing sequence, so you can Binary search for the end point, then get the length. The complexity is O(NlogN).
    • The third type is the ruler, but the length of the ruler can be changed. We just need to find a minimum length. From the starting point, make sure that the sum of the range of the ruler is not less than s, and move backward at the same time. The complexity is O(N).

The first measure code

#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn = 1e5+10;

int num[maxn],n,s;

void init() {
    scanf("%d%d",&n,&s);
    for(int i=0;i<n;i++)
        scanf("%d",&num[i]);
}

bool checke(int len) {
    int sum = 0;
    for(int i=0;i<len;i++)
        sum += num[i];
    if(sum >= s)
        return true;
    int l = 0,r = len-1;
    while(r < n) {//
        sum -= num[l];
        l++,r++;
        sum += num[r];
        if(sum >= s)
            return true;
    }
    return false;
}

int binary_search() {//二分尺取虫的长度
    int l = 1 ,r = n;
    while(r - l > 1) {
        int mid = (l + r) >> 1;
        if(checke(mid))
            r = mid;
        else
            l = mid;
    }
    return r;
}

bool check_ans() {
    int sum = 0;
    for(int i=0;i<n;i++)
        sum += num[i];
    if(sum < s)
        return true;
    return false;
}

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        init();
        if(check_ans()) {//如果总和都小于s直接输出0
            printf("0\n");
            continue;
        }
        int ans = binary_search();
        printf("%d\n", ans);
    }
    return 0;
}

The second writing code:

#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn = 1e5+10;

int sum[maxn],n,s;

void init() {
    scanf("%d%d",&n,&s);
    for(int i=1;i<=n;i++) {
        int temp;
        scanf("%d",&temp);
        sum[i] = sum[i-1]+temp;
    }
}

int solve() {
    int ans = 0x7f7f7f7f;
    for(int i=0;sum[i]+s<=sum[n];i++) {
        int last = sum[i] + s;
        int pos = lower_bound(sum+i,sum+n+1,last) - sum;//就是一个二分查找
        int len = pos - i;
        ans = min(ans,len);
    }
    return ans;
}

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        init();
        int ans = solve();
        if(sum[n] < s)
            ans = 0;
        printf("%d\n",ans);
    }
    return 0;
}

The third writing code:

#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn = 1e5+10;

int n,s,num[maxn];

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int sum,l,r,ans;
        sum = l = r = 0;
        ans = 0x7f7f7f7f;
        scanf("%d%d", &n, &s);
        for (int i = 0; i < n; i++)
            scanf("%d", &num[i]);
        while (1) {
            while (sum < s && r < n) {
                sum += num[r++];
            }
            if (sum < s)
                break;
            ans = min(ans, r - l);
            sum -= num[l++];
        }
        if (ans > n)
            ans = 0;
        printf("%d\n",ans);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324850898&siteId=291194637