POJ 3061 Subsequence 二分或者尺取法
2014-03-11 08:49
323 查看
http://poj.org/problem?id=3061
题目大意:
给定长度为n的整列整数a[0],a[1],……a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值。
思路:
方法一:
首先求出各项的和sum[i],这样可以在O(1)的时间内算出区间上的总和,这样,枚举每一个起点i,然后二分搜索出结果大于sum[i]+tot的最小下标。(tot是题目中的S)
总的时间为O(nlogn)
方法二:
设以a[s]开始的总和最初大于S时的连续子序列为a[s]+a[s+1]+……a[t-1],这时,a[s+1]+a[s+1]+……a[t-2]<a[s]+a[s+1]+……a[t-2]<S,所以如果从a[s+1]开始总和最初超过S的连续子序列是a[s+1]+……a[t‘-1],则t<=t'。
故可以设计如下算法:
1.初始s=t=sum=0
2.只要依然有sum<S,就不断将sum加上a[t],并且t=t+1;
3.如果2中无法满足sum>=s则终止,否则ans=min(ans,t-s);
4.将sum减去a[s],s+=1后回到2
总复杂度为O(N)
1.二分法
2.尺取法
题目大意:
给定长度为n的整列整数a[0],a[1],……a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值。
思路:
方法一:
首先求出各项的和sum[i],这样可以在O(1)的时间内算出区间上的总和,这样,枚举每一个起点i,然后二分搜索出结果大于sum[i]+tot的最小下标。(tot是题目中的S)
总的时间为O(nlogn)
方法二:
设以a[s]开始的总和最初大于S时的连续子序列为a[s]+a[s+1]+……a[t-1],这时,a[s+1]+a[s+1]+……a[t-2]<a[s]+a[s+1]+……a[t-2]<S,所以如果从a[s+1]开始总和最初超过S的连续子序列是a[s+1]+……a[t‘-1],则t<=t'。
故可以设计如下算法:
1.初始s=t=sum=0
2.只要依然有sum<S,就不断将sum加上a[t],并且t=t+1;
3.如果2中无法满足sum>=s则终止,否则ans=min(ans,t-s);
4.将sum减去a[s],s+=1后回到2
总复杂度为O(N)
1.二分法
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=100000+10; const int INF=0x7fffffff; int a[MAXN],sum[MAXN]; int search(int L,int R,int target) //(L,R] { while(L<R-1) { int m=(L+R)>>1; if(sum[m]<target) L=m; else R=m; } return R; } int main() { int T; scanf("%d",&T); while(T--) { int n,tot; scanf("%d%d",&n,&tot); sum[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } int ans=INF; for(int i=1;i<=n&&sum[i]+tot<=sum ;i++) { int t=search(i,n,tot+sum[i]);//sum[t]-sum[i]>=tot -> sum[t]>=tot+sum[i] ans=min(ans,t-i); } if(ans==INF) printf("0\n"); else printf("%d\n",ans); } return 0; }
2.尺取法
#include<cstdio> #include<algorithm> using namespace std; const int MAXN=100000+10; const int INF=0x7fffffff; int a[MAXN]; int main() { int T; scanf("%d",&T); while(T--) { int n,tot; scanf("%d%d",&n,&tot); for(int i=0;i<n;i++) scanf("%d",&a[i]); int s=0,t=0,sum=0,ans=INF; while(true) { while(sum<tot && t<n) { sum+=a[t++]; } if(sum<tot) break; ans=min(ans,t-s); sum-=a[s++]; } if(ans==INF) printf("0\n"); else printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ 3061 Subsequence 二分或者尺取法
- N-queens
- Sublime 2 配置编译环境[Windows]
- 表单提交前触发函数返回true表单才会提交
- BlockingQueue深入分析
- 能够同时在单片机和ANDROID下面高效运行的微GUI核心,才是好UI的基础
- build path libraries java基础--Jar包添加到build path方式说明--01
- android开发——通过子线程更新界面UI
- 使用AsyncTask异步更新UI界面及原理分析
- Android的UI设计与后台线程交互
- 在Android中实现service动态更新UI界面
- 改变UINavigationcontroller的方法 记录下来
- QuickTime SDK 7.3 for Windows
- Medoo Query的使用:执行SQL语句
- Android : UI开发ActionBar页眉
- String.Format和StringBuilder
- Cstyle的札记,R&D必读手册,第1篇 SDRAM
- Ant build.xml中的各种变量
- [ISSUE]Cannot find module 'log4js'
- iOS并发编程(上)-- NSOperation queue