[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)。
上述流程反复地推进区间的开头和末尾,来求取满足条件的最小区间。
----------------------------------------------------------------------------------------------------------------------------------------------------------
#include<iostream>
using namespace std;
int min(int a,int b){if(a>b)return b;return a;}
int main(){
int n,S,A[];
int i,j,k;
while(cin>>n>>S){
//输入数据部分
for(int i=;i<n;i++)cin>>A[i];
//尺缩法计算部分
int res=n+,s=,t=,sum=;
for(;;){
while(t<n && sum<S)sum+=A[t++];
if(sum<S)break;
res=min(res,t-s);
sum-=A[s++];
}
if(res>n)res=;
//输出结果
cout<<res<<'\n';
}
return ;
}
>>>>>>>>> 同样也可以用用lower_bound:
--------------------------------------------------------------------------------------------------------------------------------------------------------
lower_bound(ForwardIterator first,ForwardIterator last, const Type &value,Compare comp );
lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。
例如,有如下序列:
我们可以计算出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小的最小值的下标。
#include<algorithm>
using namespace std;
int min(int a,int b){if(a>b)return b;return a;}
int n,s;
int a[];
int sum[];
int main(){
while(cin>>n>>s){
//sum归0;
memset(sum,,sizeof(sum));
//输入并计算sum;
for(int i=;i<n;i++){
cin>>a[i];
sum[i+]=sum[i]+a[i];
}
//运算求解输出;
if(sum[n]<s){
cout<<""<<endl;
}
else{
int ret=n;
for(int i=;sum[i]+s<=sum[n];i++){
int t=lower_bound(sum+i,sum+n,sum[i]+s)-sum;
ret=min(ret,t-i);
}
cout<<ret<<endl;
}
}
return ;
}
>>>>>>>>附加:折半查找法:
int lowerBound(int array[],int left,int right,int value)
{
int mid=,half=;
int len=(right+left+)/;
while(len>)
{
half=len>>; //数据长度折半
mid=left+half; //计算中点
if (array[mid]<value) //调整总长与起点
{
len=len-half-;
left=mid+;
}
else
len=half;
}
return left;
}
lower_bound版本一:
int lowerBound(int array[],int left,int right,int value)
{
int mid=;
while(left<right)
{
mid=(right+left)/; //计算中点
if (array[mid]<value) //调整起点或者终点
left=mid+;
else
right=mid;
}
return right;
}
lower_bound版本二:
int upperBound(int array[],int left,int right,int value)
{
int mid=,half=;
int len=(right+left+)/;
while(len>)
{
half=len>>; //长度折半
mid=left+half; //计算中点
if (array[mid]>value) //调整长度与起点
len=half;
else
{
len=len-half-;
left=mid+;
}
}
return left;
}
upper_bound版本一:
int upperBound(int array[],int left,int right,int value)
{
int mid=;
while(left<right)
{
mid=(right+left)/; //计算中点
if (array[mid]>value) //调整起点或者终点
right=mid;
else
left=mid+;
}
return right;
}
upper_bound版本二:
int binarySearch(int array[],int left,int right,int value)
{
int mid;
while(left<=right)
{
mid=(left&right)+((left^right)>>); //防止溢出
if(array[mid]==value)
return mid;
else if (array[mid]<value)
left=mid+;
else
right=mid-;
}
return -;
}
折半查找:
[ACM_其他] 总和不小于S的连续子序列的长度的最小值——尺缩法的更多相关文章
- lintcode-397-最长上升连续子序列
397-最长上升连续子序列 给定一个整数数组(下标从 0 到 n-1, n 表示整个数组的规模),请找出该数组中的最长上升连续子序列.(最长上升连续子序列可以定义为从右到左或从左到右的序列.) 注意事 ...
- BNUOJ 4215 最长公共连续子序列
最长公共连续子序列 Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld Java class ...
- ACM-DP之最大连续子序列——hdu1231
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- HDU 1231:最大连续子序列 解题报告
第一次写博客, 自己总结写出了一道题感觉值得保存. 自己总结的规律:求最大连续子序列, 可以先求包括第N项在内的前N项最大值, (因为每一项都求过后, 前N项最大值最大的那一个元素所连续的序列即为最大 ...
- HDU 1231 最大连续子序列 &&HDU 1003Max Sum (区间dp问题)
C - 最大连续子序列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- HDU 1003 Max Sum && HDU 1231 最大连续子序列 (DP)
Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- 最大连续子序列 -- hdu -- 1231
http://acm.hdu.edu.cn/showproblem.php?pid=1231 最大连续子序列 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- K:求取数组中最大连续子序列和的四个算法
相关介绍: 求取数组中最大连续子序列和问题,是一个较为"古老"的一个问题.该问题的描述为,给定一个整型数组(当然浮点型也是可以的啦),求取其下标连续的子序列,且其和为该数组的所有 ...
- 寻找最大连续子序列/Find the max contiguous subsequence
寻找最大连续子序列 给定一个实数序列X1,X2,...Xn(不需要是正数),寻找一个(连续的)子序列Xi,Xi+1,...Xj,使得其数值之和在所有的连续子序列数值之和中为最大. 一般称这个子序列为最 ...
随机推荐
- Python 2.7_First_try_爬取阳光电影网_20161206
之前看过用Scrapy 框架建立项目爬取 网页解析时候用的Xpath进行解析的网页元素 这次尝试用select方法匹配元素 1.入口爬取页面 http://www.ygdy8.com/index.ht ...
- keyup keydown keypress 区别
测试的浏览器环境: chrome 版本 43.0.2357.134 mfirefox 版本 24.0IE6(绿色版 IE.exe)IE7IE8IE9 搜狗拼音输入法3.5(3.5.0.1089)网吧专 ...
- EAS linux挂载数据盘
查看数据盘名称 fdisk -l 假设没有挂载的数据盘为/dev/xvdb 格式化数据盘 mkfs.ext3 /dev/xvdb 添加自动挂载 mkdir /data echo '/dev/xvdb ...
- NOI 2001 食物链(eat)
1074 食物链 2001年NOI全国竞赛 时间限制: 3 s 空间限制: 64000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description ...
- WebService 基础使用&cxf第三方Service使用
1.通过Jax-ws自己发布一个webservice 解析:用webservice发布HelloWorld JAX-WS本质就是通过Socket来实现的.2.WSDL文档描述如何直接变成java代码 ...
- Hosting static website on AWS
http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html#root-d ...
- PHP 常用字符串函数整理
PHP语言中的字符串函数也是一个比较易懂的知识.今天我们就为大家总结了将近12种PHP字符串函数,希望对又需要的朋友有所帮助,增加读者朋友的PHP知识库. 1.查找字符位置函数 strpos($str ...
- mysql学习(2)-MySQL服务器优化
调优思路: 1.数据库设计与规划--以后再修该很麻烦,估计数据量,使用什么存储引擎 2.数据的应用--怎样取数据,sql语句的优化 3.mysql服务优化--内存的使用,磁盘的使用 4.操作系统的优化 ...
- zabbix网络发现
zabbix的网络自动发现是一个非常强大的功能,该功能可以完成以下工作 •快速发现并添加主机. •简单的管理. •随着环境的改变而快速搭建监控系统. 网络发现基于以下信息 •ip地址段 •基于服务的F ...
- eclipse里面设置JVM参数的问题
在run----run configuration---Agruments里面设置JVM的参数: -Xms256m -Xmx1024m 肯定还有别的方式设置,今天就先写这一种方法.待续...