POJ 3061
题意:给你 n 个正整数以及整数s,求出总和不小于 s 的连续子序列的长度最小值。若无则输出 0 ;
题解:枚举 + 二分;
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <time.h> 5 #include <math.h> 6 #include <queue> 7 #include <stack> 8 #include <list> 9 #include <set> 10 #include <map> 11 #include <vector> 12 #include <algorithm> 13 #include <iostream> 14 using namespace std; 15 16 const int NO = 100000+10; 17 int sum[NO],a[NO]; 18 int n, num; 19 20 void solve() 21 { 22 for( int i = 0; i < n; ++i ) 23 sum[i+1] = sum[i] + a[i]; 24 if( sum[n] < num ) { 25 puts( "0" ); 26 return; 27 } 28 int ret = n; 29 for( int x = 0; sum[x] + num <= sum[n]; ++x ) 30 { 31 int t = lower_bound( sum+x, sum+n, sum[x]+num ) - sum; 32 ret = min( ret, t-x ); 33 } 34 printf( "%d\n", ret ); 35 } 36 37 int main() 38 { 39 int T; 40 scanf( "%d", &T ); 41 while( T-- ) 42 { 43 memset( sum, 0, sizeof( sum ) ); 44 scanf( "%d%d", &n, &num ); 45 for( int i = 0; i < n; ++i ) 46 scanf( "%d", &a[i] ); 47 solve(); 48 } 49 return 0; 50 }
法二:尺取法:反复推进区间的开头和结尾,来求取满足条件的最小区间。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <time.h> 6 #include <queue> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <vector> 11 #include <list> 12 #include <string> 13 #include <algorithm> 14 #include <iostream> 15 using namespace std; 16 17 const int NO = 100000 + 10; 18 int a[NO]; 19 int n, s; 20 21 void solve() 22 { 23 int sum = 0, t = 0, x = 0; 24 int res = n + 1; 25 while( true ) 26 { 27 while( t < n && sum < s ) 28 sum += a[t++]; 29 if( sum < s ) break; 30 res = min( t-x, res ); 31 sum = sum - a[x++]; 32 } 33 if( res > n ) res = 0; 34 printf( "%d\n", res ); 35 } 36 37 int main() 38 { 39 int T; 40 scanf( "%d", &T ); 41 while( T-- ) 42 { 43 scanf( "%d%d", &n, &s ); 44 for( int i = 0; i < n; ++i ) 45 scanf( "%d", &a[i] ); 46 solve(); 47 } 48 return 0; 49 }