POJ——3061题 Subsequence 尺取法

r囧r小猫 2022-02-16 05:01 306阅读 0赞













Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 24814   Accepted: 10475

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

  1. 2
  2. 10 15
  3. 5 1 3 5 10 7 4 9 2 8
  4. 5 11
  5. 1 2 3 4 5

Sample Output

  1. 2
  2. 3

思路一

算法挑战上的思路是先创建一个结果数组sum1,sum1[i]的值为a数组前i项的和

然后从0开始直至后几项相加小于s时结束。期间若有解小于最小解,则更新最小解

代码如下

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. int main()
  8. {
  9. int t,n,s;
  10. int sum1[100001],a[100005];
  11. scanf("%d",&t);
  12. while(t--){
  13. scanf("%d%d",&n,&s);
  14. sum1[0]=0;
  15. for(int i=0;i<n;i++){
  16. scanf("%d",&a[i]);
  17. sum1[i+1]=sum1[i]+a[i]; //sum1数组代表a数组前i项和
  18. }
  19. if(sum1[n]<s){ //若所有项相加依旧小于s则无解
  20. printf("0\n");
  21. continue;
  22. }
  23. int minx=n; //minx标记为最小解
  24. for(int i=0;sum1[i]+s<=sum1[n];i++){ //结束条件为后i至n项相加小于s
  25. int t=lower_bound(sum1+i,sum1+n,sum1[i]+s)-sum1; //二分查找到满足从i往后数t-i项相加大于s的最小值
  26. minx=min(minx,t-i); //更新最小解
  27. }
  28. printf("%d\n",minx);
  29. }
  30. return 0;
  31. }

思路二

首先找到最开始的前几项相加大于s

然后将最靠前的一项减去,若还能大于s,则接着减去当前最靠前一项,直至不大于s,然后在依次加上后面的若干项直至再次大于s

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. int a[100005],sum1[100005];
  8. int main()
  9. {
  10. int t;
  11. cin>>t;
  12. while(t--){
  13. int n,s,sum1=0;
  14. cin>>n>>s;
  15. for(int i=0;i<n;i++){
  16. cin>>a[i];
  17. }
  18. int minx=n+1,left=0,right=0; //minx代表最小解,left代表最靠前的位置,right代表最靠后的位置
  19. for(;;){
  20. while(sum1 < s && right < n){ //加至sum1大于s或加至a数组最后一个
  21. sum1+=a[right++];
  22. }
  23. if(sum1<s){ //当最后的若干项相加已经不能大于s时跳出for循环
  24. break;
  25. }
  26. if(minx>right-left)minx=right-left; //若此时有比minx还小的解,则更新最小解
  27. sum1-=a[left++]; //将最前端的一项减去,
  28. }
  29. if(minx>n)minx=0;
  30. cout<<minx<<endl;
  31. }
  32. return 0;
  33. }

发表评论

表情:
评论列表 (有 0 条评论,306人围观)

还没有评论,来说两句吧...

相关阅读