[ACM_其他] 总和不小于S的连续子序列的长度的最小值——尺缩法

简介:


Description:

给定长度为n的整数数列,A[0],A[1],A[2]….A[n-1]以及整数S,求出总和不小于S的连续子序列的长度的最小值。如果解不存在,则输出0。

 

Input:

输入数据有多组,每组数据第一行输入n,S, (10<n<10^5,S<10^8)第二行输入A[0],A[1],A[2]….A[n-1] ( 0<A[i]≤10000),处理到文件结束。所有输入数据都在int范围之内。

Output:

每组数据输出结果占一行。

Sample Input:

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

Sample Output:

2


>>>>>>>>>这题有一个技巧,叫做尺缩法
-----------------------------------------------------------------------------------------------------------------------

(1)   设置两个指针s和t,一开始都指向数列第一个元素,此外sum=0,res=0;

(2)   只要sum<S,就将sum增加一个元素,t加1;

(3)   直到sum>=S,更新res=min(res,t-s);

(4)   将sum减去一个元素,s加1,执行(2)。

上述流程反复地推进区间的开头和末尾,来求取满足条件的最小区间。

----------------------------------------------------------------------------------------------------------------------------------------------------------

  View Code

 

>>>>>>>>> 同样也可以用用lower_bound:

   --------------------------------------------------------------------------------------------------------------------------------------------------------

   lower_bound(ForwardIterator first,ForwardIterator last, const Type &value,Compare comp );

 lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。

   例如,有如下序列:

   ia[]={12,15,17,19,20,22,23,26,29,35,40,51};
   用值21调用lower_bound(),返回一个指向22的iterator。用值22调用lower_bound(),也返回一个指向22的iterator。根据comp进行排序和比较。
  注意:::调用lower_bound之前必须确定序列为有序序列,否则调用出错。函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于    val的第一个元素位置。如果所有元素都小于val,则返回last的位置。
   --------------------------------------------------------------------------------------------------------------------------------------------------------
   所以这里我们可以这样处理:

   我们可以计算出sum(i)=a0+a1+...+ai。那么sum(t)-sum(s)=as+a(s+1)+...a(t-1)。这样我们可以实现先求出一个sum(n)。sum(n)-sum(i)=s。我们只需要去筛选sum(i)。这样可以用二分搜索的方法快速求出最小的长度。

int t=lower_bound(sum+i,sum+n,sum[i]+s)-sum;求出来的是从ai到at(i<=t<=n)和比s小的最小值的下标。

  View Code

 

>>>>>>>>附加:折半查找法:

  lower_bound版本一:
  lower_bound版本二:
  upper_bound版本一:
  upper_bound版本二:
  折半查找:

 



本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/3485545.html,如需转载请自行联系原作者

相关文章
|
2月前
|
算法 前端开发
最大公因数等于 K 的子数组数目
最大公因数等于 K 的子数组数目
22 0
|
4月前
|
算法 测试技术 C#
C++前缀和算法的应用:统计得分小于K的子数组数目
C++前缀和算法的应用:统计得分小于K的子数组数目
|
3月前
|
Python
计算小于或等于n的非负整数区间包含的1的数量
计算小于或等于n的非负整数区间包含的1的数量
22 0
|
3月前
leetcode-674:最长连续递增序列
leetcode-674:最长连续递增序列
26 0
|
10月前
|
索引
长度最小的子数组
长度最小的子数组
|
10月前
|
机器学习/深度学习
欧拉函数:求小于等于n且与n互质的数的个数
求小于等于n且与n互质的数的个数 互质穷举法 互质:两个数互质代表两者最大公约数为1 最大公约数求法:辗转相除法,最小公倍数:较大值除以最大公约数乘以较小值 辗转相除法: 较大的数a取模较小的数b,得取模值c 若取模值等于0 则最大公约数为取模值,否则继续下一步 a与c再次取模,回到第二步 //求最大公约数gcd以及最大公倍数lcm // 36 24 36/24 // 24 12 24/12 // 0 结束最大公约数为12 // 求最小公倍数 // lcm(a, b) = (a * b)/g
86 0
小于等于K的最大子数组累加和
小于等于K的最大子数组累加和
|
12月前
|
存储
Leetcode——485. 最大连续 1 的个数
文章目录 1、题目 2、滑动窗口 3、一次遍历(官方题解)
Leetcode——485. 最大连续 1 的个数
leetcode 674 最长连续递增序列
leetcode 674 最长连续递增序列
66 0
leetcode 674 最长连续递增序列
|
算法 Java
最长连续递增序列(LeetCode 674)
最长连续递增序列(LeetCode 674)
41 0