zoukankan      html  css  js  c++  java
  • Subsequence---poj3061(尺取法||二分)

    题目链接:http://poj.org/problem?id=3061

    题意:给n个正整数和一个数S,求出总和不小于S的连续子序列的长度的最小值,如果无解输出0;

    我们可以用sum[i]表示前i项的和;然后二分枚举找答案即可时间复杂度为O(n*logn)的;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    using namespace std;
    #define N 120000
    #define PI 4*atan(1.0)
    #define mod 110119
    #define met(a, b) memset(a, b, sizeof(a))
    typedef long long LL;
    
    int a[N], n, s, sum[N];
    
    int Judge(int len)
    {
        for(int i=1; i+len-1<=n; i++)
        {
            if(sum[i+len-1]-sum[i-1]>=s)
                return 1;
        }
        return 0;
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d %d", &n, &s);
    
            for(int i=1; i<=n; i++)
            {
                scanf("%d", &a[i]);
                sum[i] = sum[i-1] + a[i];
            }
    
            int L = 1, R = n, Min = 0;
    
            while(L <= R)
            {
                int Mid = (L+R)/2;
                if(Judge(Mid))
                {
                    Min = Mid;
                    R = Mid-1;
                }
                else
                    L = Mid+1;
            }
            printf("%d
    ", Min);
        }
        return 0;
    }
    View Code

    还可以用尺取法,就是用两个指针控制一下头和尾,然后移动即可;时间复杂度是O(n)的;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    using namespace std;
    #define N 120000
    #define PI 4*atan(1.0)
    #define mod 110119
    #define met(a, b) memset(a, b, sizeof(a))
    typedef long long LL;
    
    int a[N], n, s;
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d %d", &n, &s);
            
            for(int i=1; i<=n; i++)
                scanf("%d", &a[i]);
                
            int L = 1, R = 1, ans = n+1, sum = 0;
            
            while(1)
            {
                while(R<=n && sum<s) 
                    sum += a[R++];
                if(sum < s) break;
                ans = min(ans, R-L);
                sum -= a[L++];
            }
            if(ans == n+1)ans = 0;
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    中移动ipv6-老毛子固件获取ipv6设置
    win7-win10 禁用IPV6临时地址
    辅助调用函数【call,apply,bind】
    Unraid修改docker镜像地址&默认启动
    docker基本入门知识-小白向
    [不止于代码]Unraid基本使用速记
    Dockerfile文件说明
    Git之pull,fetch差别
    代码片段添加智能提示,打造一款人见人爱的ORM框架
    新定义三层,指挥官模式
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5786260.html
Copyright © 2011-2022 走看看