UVALive2678子序列
2014-01-18 17:03
281 查看
UVALive2678 http://122.207.68.93:9090/csuacmtrain/problem/viewProblem.action?id=453§ |
【题目描述】:n个正整数组成的序列。给定整数S,求长度最短的连续序列,使他们的和大于等于S。 |
【算法分析】: 【二分】: 全是正整数,保证取的连续序列长度越长,和越可能大于等于S,所以满足二分的单调递增的条件,而这里,我们要找的最优解是最小的长度,就是和刚刚好大于等于S的区间长度。 【区间和优化到O(N)】: 使用C[i]数组,做差求和。方法不细说。要求自己,以后遇到区间求和问题,自然就要想到这个。 【运筹分析】: 决策方案:所有区间段,sigm(n+(n-1).......+1) == O(n^2)注意n<=10^5 限制条件:累和大于等于S 最优评判标准:区间长度最小 |
【完整代码】:#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<stdlib.h> #include<math.h> #include<queue> #include<vector> #include<map> #define MAXN 100000+5 #define MAXM 20000+5 #define oo 9556531 #define eps 0.000001 #define PI acos(-1.0)//这个精确度高一些 #define REP1(i,an) for(int i=0;i<=(n);i++) #define REP2(i,n) for(int i=1;i<=(n);i++) using namespace std; //这道题不是dp,而是二分,一是因为dp本身会超时,二是连续的状态是单调递增的 int A[MAXN]; int C[MAXN]; int n,s; bool isok(int l) { for(int i=l;i<=n;i++) if(C[i]-C[i-l]>=s) return true;//优化到O(n) return false; } int main() { while(cin>>n>>s) { C[0]=0; for(int i=1;i<=n;i++) { cin>>A[i]; C[i]=C[i-1]+A[i]; } int l=1,r=n+1; while(l<r)//边界条件,保证能够跳出循环,找不到极值也可,画状态图确定 { int m=(l+r)/2; if (isok(m)) r=m;else l=m+1;//根据除2取左的特点,保证能取到极值点 } if (isok(l)) cout<<l<<endl;else cout<<0<<endl; } return 0; } |
【关键词】:二分,思维 |
相关文章推荐
- openerp修改logo和title
- android应用开发揭秘第13章01示例,移动图像,opengl绘制星星问题解决!
- Cocos2d-x 3.0 新特性体验(1)创建项目+运行sample+新特性内容
- Future和FutureTask
- 贪心算法-活动选择问题
- 国内外有名的安全扫描工具,你知道几个?
- android应用开发揭秘第13章01示例,移动图像,opengl绘制星星问题解决!
- sqoop安装遇到的问题
- Django:第一个简单的django程序
- Ubuntu软件仓库-转载
- 数据挖掘读书笔记 -- 常见数据处理技巧
- 子元素过滤器的应用
- 淘宝u站推广—U站推广必用的框架代码和跳转
- 练习3-2
- AES加密算法模式
- Spring Security教程(12)---- 使用数据库来管理方法
- [unity3d]unity平台的预处理
- 使用 Sandcastle 生成代码帮助文档
- Lua程序数据类型及其使用
- 关于java内存模型与java线程模型