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

题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度、否则输出 0(序列的元素都是大于 0 小于10000)

分析 : 有关子序列和的问题,都可以考虑采用先构造前缀和的方式来进行接下来的操作 ( 任意子序列的和都能由某两个前缀和的差表示 )。

二分做法 ==> 我们枚举起点,对于每一个起点 St 二分查找看看 St 后面有没有前缀和是大于或者等于 [ St的前缀和 ] + S 的,如果有说明从当前起点开始有一个终点使得起终之和是大于或者等于 S 的,在这个过程中维护最小长度即可!时间复杂度为 O(nlogn)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;

int arr[maxn], sum[maxn];
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    sum[0] = 0;
    while(nCase--){
        int n, s;
        scanf("%d %d", &n, &s);

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

        if(sum[n] < s){
            puts("0");
            continue;
        }

        int ans = n;
        for(int i=1; i<=n; i++){
            int st = i - 1;
            int en = lower_bound(sum+st, sum+n, sum[st]+s) - sum;
            //printf("%d %d\n", st, en);
            if(sum[en] - sum[st] < s) continue;
            ans = min(ans, en - st);
        }

        printf("%d\n", ans);
    }
    return 0;
}

尺取做法 ==> 如果有一个满足条件的子序列为 arr[st]...arr[en-1] >= S,那么肯定有 arr[st+1]...arr[en-2] < arr[st]...arr[en-2] < S,所以如果将 st+1 作为起点也有满足条件的序列且令其终点为en‘-1,那么必定有 en‘-1 >= en-1,那么也就是说当前枚举完 st 这个点,其贡献的答案是 (en-1)-st+1,现在我们考虑 st+1 即下一个起点的时候考虑的终点应该是要考虑大于或者等于 en-1 的点,故尺取是正确的解法。时间复杂度为O(n)

///尺取法
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;

int sum[maxn];
int main(void)
{
    sum[0] = 0;

    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        int n, s;
        scanf("%d %d", &n, &s);

        int tmp;
        for(int i=1; i<=n; i++)
            scanf("%d", &tmp),
            sum[i] = sum[i-1] + tmp;///统计前缀和

        if(sum[n] < s){
            puts("0");
            continue;
        }

        int L, R, ans;///左指针、右指针
        ans = n;
        L = R = 1;

        while(L <= R && R <= n){
            if(sum[R] - sum[L] < s) R++;
            else{
                ans = min(ans, R-L);
                L++;
            }
        }

        printf("%d\n", ans);
    }
    return 0;
}

时间: 2024-10-21 21:18:29

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

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 (二分||尺取法)

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

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