POJ 3061 Subsequence (二分||尺取法)

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

题意:

求出总和不小于S的连续子序列的长度的最小值。

题解:

二分查找的话,前缀和是满足单调性的,计算从每一个数开始总和刚好大于s的长度。具体实现就是
二分搜索s[i]+s是否存在于前缀和数组中,就是查找以i+1开头的总和刚好大于s的最短长度。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=1e5+5;
int sum[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,S;
        cin>>n>>S;
        for(int i=0;i<n;i++)
        {
            int x;
            cin>>x;
            sum[i+1]=sum[i]+x;
        }
        if(sum[n]<S)
        {
            puts("0");
            continue;
        }
        int res=n;
        for(int s=0;sum[s]+S<=sum[n];s++)
        {
            int t=lower_bound(sum+s,sum+n,sum[s]+S)-sum;
            res=min(res,t-s);
        }
        cout<<res<<endl;
    }
    return 0;
}

解法二:尺取法
反复地推进区间的开头和末尾,来求取条件的最小区间的方法被称为尺取法。
因为很懒,所以直接贴图片了。

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        int s=0,t=0,sum=0;
        for(int i=0;i<n;i++)
            cin>>a[i];
        int res=n+1;
        for(;;)
        {
            while(t<n&&sum<k)
                sum+=a[t++];
            if(sum<k)
                break;
            res=min(res,t-s);
            sum-=a[s++];
        }
        if(res>n)
            res=0;
        cout<<res<<endl;
    }
    return 0;
}
时间: 2024-08-08 03:30:11

POJ 3061 Subsequence (二分||尺取法)的相关文章

POJ 3061 Subsequence ( 二分 || 尺取法 )

题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用先构造前缀和的方式来进行接下来的操作 ( 任意子序列的和都能由某两个前缀和的差表示 ). 二分做法 ==> 我们枚举起点,对于每一个起点 St 二分查找看看 St 后面有没有前缀和是大于或者等于 [ St的前缀和 ] + S 的,如果有说明从当前起点开始有一个终点使得起终之和是大于或者等于 S 的,

POJ 3061 Subsequence(尺取法)

传送门 Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11284 Accepted: 4694 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) ar

POJ 3061 Subsequence(尺取法)

题目链接:http://poj.org/problem?id=3061 题意:给定长度为n的数列整数,以及整数S,求出总和不少于S的连续子序列的长度的最小值.如果解不存在,则输出0. 尺取法:通常是指对数组保存一对下标(起点,终点),然后根据实际情况交替推进两个端点直到解决问题的方法,这个操作很像尺蠼虫故得名. 思路:所以可以先初始化起点s,终点g,再一步一步推进,直到sum>S,然后记录此时的序列长度,再推进s,sum-=num[s],再记录长度,直到sum<S,再推进g,这样的方法,s和g

[ACM] POJ 3061 Subsequence (尺取法)

Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8403   Accepted: 3264 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

从具体题目来谈尺取法 POJ 3061 Subsequence

题目链接:http://poj.org/problem?id=3061 先说说最朴素的算法,那就是for嵌套了,复杂度是O(n^3)太慢,想都不用想一定会超时.接下来有的人可能会想到二分搜索的思想,将时间复杂度优化成O(n*logn),我试了一下,可以AC. 但是这都不是今天要说的重点,今天要说的是一个ACM比赛中常用的技巧方法——尺取法.这是一种可以直接将时间复杂度优化到O(n)的算法. 我们先来介绍一下尺取法.尺取法,顾名思义,像尺子一样,一块一块的截取.是不是解释的有点让人纳闷-..没关系

poj3061 Subsequence ,尺取法

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 sequen

hihocoder-1483区间价值 (二分+尺取法)

题目链接: 区间价值 给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同.小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示. 例如1 1 1 2 2这五个数所组成的区间的价值为4. 现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少. Input 第一行一个数T(T<=10),表示数据组数. 对于每一组数据: 第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1

51nod-1686 第K大区间(二分+尺取法)

题目链接: 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. Input 第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2) 第二行n个数,0<=每个数<2^31 Output 一个数表示答案. Input示例 4 2 1 2 3 2 Output示例 2 题意: 思路: 先把数组都离散为[1,n]的数,注意相等的;再二分答案t,check区间众数

poj 2566 Bound Found 尺取法 变形

Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 2277   Accepted: 703   Special Judge Description Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration