题目大意 给定一个长度为N的数列,以及整数S。求出和不小于S的连续子序列的长度的最小值。如果解不存在,则输出0.
题目分析 先求前缀和,然后就能用O(1)的时间, 求出一个区间的和。
之后用二分就能解决这道题。
但《挑战程序设计竞赛》(P146)中提供了一种更高效和简单的解法,叫“尺取法”。
source code solution 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include  <iostream>  using  namespace  std ;const  int  maxn = 100010 ;typedef  long  long  ll;ll a[maxn], sum[maxn]; int  N;ll S; bool  judge (int  len)      for  (int  i = 0 ; i + len <= N; i++) {         if  (sum[i + len] - sum[i] >= S) return  true ;     }     return  false ; } int  main ()      ios::sync_with_stdio(false );     cin .tie(0 );     int  T;     cin  >> T;     while  (T--) {        cin  >> N >> S;        for  (int  i = 0 ; i < N; i++) cin  >> a[i];        sum[0 ] = 0 ;        for  (int  i = 0 ; i < N; i++) sum[i + 1 ] = sum[i] + a[i];        if  (sum[N] < S) {            cout  << 0  << endl ;            continue ;        }         int  L = 0 , R = N;        while  (L + 1  < R) {            int  mid = (L + R) / 2 ;            if  (judge(mid)) R = mid;            else  L = mid;        }        cout  << R << endl ;     } } 
solution 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include  <iostream>  #include  <algorithm>  using  namespace  std ;const  int  maxn = 100010 ;typedef  long  long  ll;ll a[maxn]; int  N;ll S; int  main ()      ios::sync_with_stdio(false );     cin .tie(0 );     int  T;     cin  >> T;     while  (T--) {        cin  >> N >> S;        for  (int  i = 0 ; i < N; i++) cin  >> a[i];        int  s = 0 , t = 0 ;        ll sum = 0 ;        int  ans = N + 1 ;        for  (;;) {            while  (t < N && sum < S) sum += a[t++];            if  (sum < S) break ;            ans = min(ans, t - s);            sum -= a[s++];        }        if  (ans > N) ans = 0 ;        cout  << ans << endl ;            } } 
 
        
    
    
        
    Last updated: 2018-05-02 14:38:14