zoukankan      html  css  js  c++  java
  • 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 }
    View Code
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Spring boot项目搭建及简单实例
    nodejs的web开发框架之express(其中项目的案例也是后端渲染)
    node的系统核心模块实现服务器功能、用nodejs做动态网站(后端渲染)
    nodejs包管理工具npm 、yarn
    node的基本操作、文件路径、文件读、取、目录读取删
    了解node、ES6
    相对单位em、rem
    响应式开发---网页的布局方式、媒体查询、栅格化布局、less语言
    移动端插件的使用---zepto、iScroll、swiper、swipe、fastclick
    base.css
  • 原文地址:https://www.cnblogs.com/itdef/p/12059730.html
Copyright © 2011-2022 走看看