uva 1121 Subsequence
Posted Omz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva 1121 Subsequence相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVA-1121
题意:
给出一个正整数数列a,要求找出最短的连续的一个序列使得这个序列的所有数字之和大于等于S。
思路:
第一是由于序列都是正整数,所以他们的前缀和是递增的,就可以用二分搜索,但是我的二分是二分的个数,这个具体看代码。复杂度O(NlogN)。
1 #include <stdio.h> 2 #include <string.h> 3 4 int a[100005]; 5 int s; 6 int n; 7 8 bool meet(int k) 9 { 10 int sum = 0; 11 12 for (int i = 0;i < k;i++) 13 sum += a[i]; 14 15 if (sum >= s) return 1; 16 17 for (int i = k;i < n;i++) 18 { 19 sum -= a[i-k]; 20 sum += a[i]; 21 22 if (sum >= s) return 1; 23 } 24 25 return 0; 26 } 27 28 int main() 29 { 30 while (scanf("%d%d",&n,&s) != EOF) 31 { 32 for (int i = 0;i < n;i++) 33 scanf("%d",&a[i]); 34 35 int l = 1,r = n; 36 37 if (!meet(n)) 38 { 39 printf("0\n"); 40 41 continue; 42 } 43 44 while (l < r) 45 { 46 int mid = (l + r) >> 1; 47 48 if (meet(mid)) r = mid; 49 else l = mid + 1; 50 } 51 52 while (r - 1 > 0 && meet(r-1)) r--; 53 54 printf("%d\n",r); 55 } 56 57 return 0; 58 }
第二个思路就是用尺取法,可以到达O(N)的复杂度。
具体就是设置一个起始位置start,然后end指针从第一个元素开始遍历,当sum[end] - sum[start] < s的时候,把end指针右移,当满足sum[end] - sum[start] >= s的时候,就把start指针向右移,然后更新ans的值。
复杂度的分析:由于start是一直递增的,然后它最多递增n次,所以复杂度是O(N)。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 int a[100005],b[100005]; 7 8 int main() 9 { 10 int n,s; 11 12 while (scanf("%d%d",&n,&s) != EOF) 13 { 14 for (int i = 1;i <= n;i++) scanf("%d",&a[i]); 15 16 b[0] = 0; 17 18 for (int i = 1;i <= n;i++) b[i] = b[i-1] + a[i]; 19 20 int start = 0; 21 22 int ans = n + 1; 23 24 for (int i = 1;i <= n;i++) 25 { 26 if (b[i] - b[start] < s) continue; 27 28 while (b[i] - b[start] >= s) start++; 29 30 ans = min(ans,i - start + 1); 31 } 32 33 if (ans == n + 1) printf("%d\n",0); 34 else printf("%d\n",ans); 35 } 36 37 return 0; 38 }
以上是关于uva 1121 Subsequence的主要内容,如果未能解决你的问题,请参考以下文章
UVA10871 Primed Subsequence欧拉筛法
UVA 10405 Longest Common Subsequence
UVA 11404Palindromic Subsequence