1. 程式人生 > >Subsequence(POJ 3061)

Subsequence(POJ 3061)

序列 second greate amp read rst 利用 etc separate

  • 原題如下: 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(\n);
    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(\n);
    65         --m;
    66     }
    67 }

Subsequence(POJ 3061)