• Subsequence(POJ 3061)


    • 原题如下:
      Subsequence
      Time Limit: 1000MS   Memory Limit: 65536K
      Total Submissions: 21032   Accepted: 8975

      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
    • 题解:由于所有的元素大于0,假设存在子序列[s,t)满足as+…+at-1≥S,那么对于任何的t'>t一定有as+…+at'-1≥S。另外,如果令sum(i)=a0+a1+…+ai-1,那么as+as+1…+at-1=sum(t)-sum(s),所以预先计算好sum的话,可以用O(1)的时间计算区间上的总和,这样一来,子序列的起点s确定以后,便可以用二分搜索快速确定使序列和不小于S的结尾t的最小值,这个算法的复杂度是O(nlogn)。还有一种更为高效的算法,设以as开始总和最初大于S时的连续子序列为as+…+at-1,这时,as+1+…+at-2<as+…+at-2<S,所以从as+1开始总和最初超过S的连续子序列如果是as+1+…+at'-1的话,必然有t'≥t。利用这一性质,可设计如下算法:
      ①以s=t=sum=0初始化
      ②只要依然有sum<S,就不断将sum增加at,并将t增加1
      ③如果②中无法满足sum≥S则终止,否则,更新res=min(res, t-s)
      ④将sum减去as,s增加1然后回到②
      对于这个算法,因为s,t只能不断地增大,最多变化n次,因此只需O(n)的复杂度就可以求解这个问题了,像这样反复地推进区间的开头和结尾,来求取满足条件的最小区间的方法被称为尺取法。
    • 代码1:
       1 #include <cstdio>
       2 #include <cctype>
       3 #include <algorithm>
       4 #include <cmath>
       5 #define num s-'0'
       6 
       7 using namespace std;
       8 
       9 const int MAX_N=1000000;
      10 const int INF=0x3f3f3f3f;
      11 int n,S,t;
      12 int a[MAX_N],sum[MAX_N+1];
      13 
      14 int min(int x, int y)
      15 {
      16     if (x<y) return x;
      17     return y;
      18 }
      19 
      20 void read(int &x){
      21     char s;
      22     x=0;
      23     bool flag=0;
      24     while(!isdigit(s=getchar()))
      25         (s=='-')&&(flag=true);
      26     for(x=num;isdigit(s=getchar());x=x*10+num);
      27     (flag)&&(x=-x);
      28 }
      29 
      30 void write(int x)
      31 {
      32     if(x<0)
      33     {
      34         putchar('-');
      35         x=-x;
      36     }
      37     if(x>9)
      38         write(x/10);
      39     putchar(x%10+'0');
      40 }
      41 
      42 int main()
      43 {
      44     read(t);
      45     while (t>0)
      46     {
      47         read(n);read(S);
      48         for (int i=0; i<n; i++) 
      49         {
      50             read(a[i]);
      51             sum[i+1]=sum[i]+a[i];
      52         }
      53         int res=n+1;
      54         for (int s=0; sum[n]-sum[s]>=S; s++)
      55         {
      56             int t=lower_bound(sum+s,sum+n,sum[s]+S)-sum;
      57             res=min(res,t-s);
      58         }
      59         if (res<=n) write(res);
      60         else write(0);
      61         putchar('
      ');
      62         --t;
      63     }
      64 }

       代码2:

       1 #include <cstdio>
       2 #include <cctype>
       3 #include <algorithm>
       4 #include <cmath>
       5 #define num s-'0'
       6 
       7 using namespace std;
       8 
       9 const int MAX_N=1000000;
      10 const int INF=0x3f3f3f3f;
      11 int n,S,m;
      12 int a[MAX_N];
      13 
      14 int min(int x, int y)
      15 {
      16     if (x<y) return x;
      17     return y;
      18 }
      19 
      20 void read(int &x){
      21     char s;
      22     x=0;
      23     bool flag=0;
      24     while(!isdigit(s=getchar()))
      25         (s=='-')&&(flag=true);
      26     for(x=num;isdigit(s=getchar());x=x*10+num);
      27     (flag)&&(x=-x);
      28 }
      29 
      30 void write(int x)
      31 {
      32     if(x<0)
      33     {
      34         putchar('-');
      35         x=-x;
      36     }
      37     if(x>9)
      38         write(x/10);
      39     putchar(x%10+'0');
      40 }
      41 
      42 int main()
      43 {
      44     read(m);
      45     while (m>0)
      46     {
      47         read(n);read(S);
      48         for (int i=0; i<n; i++) 
      49         {
      50             read(a[i]);
      51         }
      52         int s,t,sum;
      53         s=t=sum=0;
      54         int res=n+1;
      55         for (;;)
      56         {
      57             while (t<n && sum<S) sum+=a[t++];
      58             if (sum<S) break;
      59             res = min(res,t-s);
      60             sum-=a[s++];
      61         }
      62         if (res>n) res=0;
      63         write(res);
      64         putchar('
      ');
      65         --m;
      66     }
      67 }
  • 相关阅读:
    UDP协议测试
    openstack ussusi ubuntu 20 centos8 dracut initqueue timeout
    wol linux远程通过数据帧自动开机
    openStack proformancee bottlenecks options optimized
    find 搜索排除搜索目录
    Ipv6
    golang学习笔记 ---日志库 logrus
    golang学习笔记---- 格式化IO
    golang学习笔记 --- struct 嵌套
    golang学习笔记---HTTPS
  • 原文地址:https://www.cnblogs.com/Ymir-TaoMee/p/9509440.html
Copyright © 2020-2023  润新知