poj 3061 Subsequence 二分 前缀和 双指针
地址 http://poj.org/problem?id=3061
解法1
使用双指针
由于序列是连续正数
使用l r 表示选择的子序列的起始
每当和小于要求的时候 我们向右侧扩展 增大序列和
每当和大于等于要求的时候 我们将子序列左边的数字剔除 看能是在减少长度情况下 还能保持子序列和满足要求
这样在指定起点下的满足要求的最短子序列和都会被记录 然后在比较出最短长度的子序列
如图
代码

1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <memory.h> 5 #include <queue> 6 7 8 using namespace std; 9 10 11 /* 12 Sample Input 13 6 14 10 15 15 5 1 3 5 10 7 4 9 2 8 16 5 11 17 1 2 3 4 5 18 1 2 19 1 20 1 1 21 5 22 3 9999 23 1 2 3 24 3 0 25 1 2 3 26 27 Sample Output 28 2 29 3 30 */ 31 const int MAX_N = 1000010; 32 int n, m; 33 int nums[MAX_N]; 34 35 int ret = MAX_N; 36 37 void solve() 38 { 39 int sum = 0; 40 int minlen = MAX_N; 41 42 int r = -1; int l = 0; 43 44 while (1) { 45 if (sum < m) { 46 r++; 47 if (r >= n) break; 48 sum += nums[r]; 49 } 50 else { 51 //sum >= m 52 minlen = min(minlen, r - l + 1); 53 sum -= nums[l]; 54 l++; 55 if (l >= n) break; 56 if (l > r) { 57 r = l; 58 sum = nums[l]; 59 } 60 } 61 } 62 63 64 if (minlen == MAX_N) minlen = 0; 65 cout << minlen << endl; 66 } 67 68 69 int main() 70 { 71 int loop; 72 cin >> loop; 73 while (loop--) { 74 cin >> n >> m; 75 76 for (int i = 0; i < n; i++) { 77 cin >> nums[i]; 78 } 79 ret = MAX_N; 80 solve(); 81 } 82 83 return 0; 84 }
//=========================================================================================
解法2 二分查找前缀和 todo
使用前缀和就可以快速定位各个子序列的和
然后使用二分查找进行查找以指定索引开始的子序列满足和要求的最短长度
最后得到所有满足需求中最短的子序列长度
代码如下

1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 6 const int MAX_N = 1000010; 7 int n, m; 8 int nums[MAX_N]; 9 int preSum[MAX_N]; 10 11 12 int binartSearch(int sum[],int l, int r) 13 { 14 int start = l; 15 while (l < r) { 16 int mid = (l + r) >> 1; 17 if (sum[mid] - sum[start] >= m) { 18 r = mid; 19 } 20 else { 21 l = mid + 1; 22 } 23 } 24 25 return (l-start); 26 } 27 28 int solve() 29 { 30 int ret = MAX_N; 31 for (int i = 1; i <= n; i++) { 32 preSum[i] = preSum[i - 1] + nums[i]; 33 } 34 //全部加起来都无法达到标准 35 if (preSum[n] < m) return 0; 36 37 for (int i = 1; i < n; i++) { 38 //if(preSum[i]+m <= preSum[n]){ 39 if (preSum[n] - preSum[i] >= m) { 40 int idx = binartSearch(preSum,i,n); 41 ret = min(ret, idx); 42 } 43 } 44 45 if (ret == MAX_N) ret = 0; 46 return ret; 47 } 48 49 50 int main() 51 { 52 int loop; 53 cin >> loop; 54 55 while (loop--) { 56 cin >> n >> m; 57 memset(nums,0,sizeof(nums)); 58 memset(preSum, 0, sizeof(preSum)); 59 60 for (int i = 1; i <= n; i++) { 61 cin >> nums[i]; 62 } 63 cout << solve() << endl; 64 } 65 66 return 0; 67 }
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
2014-12-18 C++ 提取网页内容系列之三
2014-12-18 C++ 提取网页内容系列之二
2014-12-18 C++ 提取网页内容系列之一