Subsequence

来源:互联网 发布:java反序列化代码 编辑:程序博客网 时间:2024/06/17 11:34

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

题意大概就是给定case数,每个case给定序列大小和一个值,最后让你求和不小于这个值的最短的子序列。读题之后就知道是遍历这个序列然后找到序列最小值,所以定义变量ans来保存这个最小值,并且初值设置为序列size+1;那么如何使遍历序列复杂度尽可能小呢?(普通做法是N^2复杂度)特别机智的尺取法就出现啦!此处给一个例子解释尺取法:给定序列是  5 1 3 5 10 7 4 9 2 8 给定值是15我们用一个变量start来记录我们取的子序列的起始下标,那么开始是start=0,用end来表示我们取的子序列的结束下标,初始化为0,定义sum=0记录现取子序列的和。华丽丽的尺取法开始了!我们将sum+=a[end++],直到sum不小于15。此时的子序列为5 1 3 5 10接下来将sum中start对应值弹出,并将start++,再判断sum是否仍不小于给定值,若sum仍不小于给定值,重复当前步骤。可以知道执行完这一步之后的序列为:5 10当start再往右移时,会发现sum不满足条件了,那么该怎样呢,此时再右移end,扩大选取的序列的大小即可。基本原理就是这样,ac代码如下:
#include<iostream>#include<algorithm>using namespace std;int a[100006];void solve(int n,int S){    int ans = n + 1;    int s = 0, t = 0, sum = 0;    for (;;)    {        while (t < n&&sum < S)        {            sum += a[t++];        }        if (sum < S)break;        ans = min(ans, t - s);        sum -= a[s++];    }    if (ans > n)        cout << '0' << endl;    else    cout << ans << endl;}int main(){    int n, Case,S;    cin >> Case;    while (Case--)    {        //int a[100000];        cin >> n;        cin >> S;        for (int i = 0; i < n; i++)        {            cin >> a[i];        }        solve(n,S);    }}
原创粉丝点击