文章目录

  • 最少连续页(poj3320)
    • 分析题意
      • 第一步:找第一个满足条件区间
      • 第二步:开始将左端边界向右移,达到“缩小”区间、减少连续页的目的。
    • 归纳总结代码

尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以说尺取法是一种高效的枚举区间的方法,是一种技巧,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案,所以要先判断是否可以使用尺取法再进行计算。

本人为一名普通二本学校自动化专业的大二学生,对编程有着少许兴趣。
最近想了解什么是尺取法,于是想写道简单尺取法相关的题目,当练一练手。

最少连续页(poj3320)

题意:一本书有P页,每一页都一个知识点,求去最少的连续页数覆盖所有的知识点。

样例
输入:
6
1 1 3 1 2 3
输出:
3
备注:一本书有6页,第一页知识点为1…第6页知识点为3。

分析题意

按照尺取法的定义:一种高效的枚举区间的方法。我们应该先在找一个满足条件的区间(不一定是最优),然后再通过将左边界向右移、右边界向右移的方式需找最优区间。

第一步:找第一个满足条件区间

为了能够更好地找到最优区间,我们需要先了解有多少个不同的知识点、在已读的页数中每个知识点出现了几次。

map <int, int> cnt;
set <int> t;
//set主要是统计不同的知识点
//set不允许重复插入 每个元素都是不同的
//用map记录每个知识点在连续页中出现的次数

①:可以用set容器“不能重复插入”的特性,统计书中出一共有多少个不同的知识点。

    for (int i = 0; i < p; i++){ scanf("%d", &a[i]);t.insert(a[i]);}int num = t.size();

插入个数 num=3
②:可以用map容器“映射”的特性,统计出在已读的页数中相同知识点出现次数。

        while (end<p && sum<num){  //选取不同知识点 if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;}
第二步:开始将左端边界向右移,达到“缩小”区间、减少连续页的目的。

begin:左边界下标 end:右边界下标
ans:当前已读最少连续页

在满足条件的区间里
如果右边界下标减去左边界下标小于当前已读最少连续页。
那么右边界下标减去左边界下标就是当前最少页数。
如果end-begin<ans,则ans=end-begin+1。

初始状态(第一个满足条件区间)

当前状态:begin=0 end=4 ans=5

当a[0]知识点在已读页数出现过,则将左边界向右移,右边界不变。
当前状态:begin=1 end=4 ans=4

当a[1]知识点在已读页数出现过,左边界向右移,右边界不变。
当前状态:begin=2 end=4 ans=3

当a[2]知识点在已读页数未出现过右边界要向右移,找到满足条件的区间。
当前状态:begin=3 end=4 ans=3


当前状态:begin=1 end=5 ans=3

右边界找到合适位置后,左边界再向右移。
此时a[3]知识点在已读页数未出现过右边界要向右移,找到满足条件的区间。可是右边界已经到达最后一页,结束查找。
最终得到最少页数为3。

    while (1){   //begin:左边界  end:右边界 //num不同的知识点 sum已读知识点 while (end<p && sum<num){  //选取不同知识点 if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;} //读完了,退出循环 if (end==p) break;//判断有没有更小的连续页  if(ans>end-begin)ans = end-begin;//ans=end-begin//因为end在上面循环中多加了一个1 //向前推 cnt[a[begin]]--;if(cnt[a[begin]]==0)sum--; begin++;}
归纳总结代码

通俗版

//通俗版
#include <bits/stdc++.h>
#include<algorithm>
#include <set>
#include <map>
#define MAX 1000010
#define ll long long
#define INF 1000010
using namespace std;
int a[MAX];
map <int, int> cnt;
set <int> t;int main()
{int p, ans = INF, begin=0, end=0, sum=0;scanf("%d", &p);for (int i = 0; i < p; i++){ scanf("%d", &a[i]);t.insert(a[i]);}int num = t.size();while (1){   while (end<p && sum<num){   if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;} if (end==p) break;if(ans>end-begin)ans = end-begin;cnt[a[begin]]--;if(cnt[a[begin]]==0)sum--; begin++;}cout<<ans<<endl;return 0;
}

精简版(来源网上)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <map>
#define MAX 1000010
#define LL long long
#define INF 0x3f3f3f3fusing namespace std;
int a[MAX];
map <int, int> cnt;
set <int> t;
int p, ans = INF, st, en, sum;int main()
{scanf("%d", &p);for (int i = 0; i < p; i++) scanf("%d", a+i), t.insert(a[i]);int num = t.size();while (1){while (en<p && sum<num)if (cnt[a[en++]]++ == 0) sum++;if (sum < num) break;ans = min(ans, en-st);if (--cnt[a[st++]] == 0) sum--;}printf("%d\n", ans);return 0;
}

希望能够将自己的一些学习经验分享给有需要的人。
我是小郑,一个坚持不懈的小白。
博客参考链接

尺取法(图文解析、初学推荐)相关推荐

  1. 尺取法 --算法竞赛专题解析(2)

    本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当      作者签名书 如有建议, ...

  2. POJ-2566,HDU-1058,POJ-3320,POJ-3061(尺取法)

    题目链接: Bound Found 思路 用前缀和先统计每个数到第一个数的总和.因为尺取法需要数组有序,所以对前缀和得到的数组排序.设立两个类似指针了l,r,使得l,r不断前进,并记录这之间产生的最小 ...

  3. (尺取法模板题) QLU_ACM 2021 专题训练(一) D - Subsequence 题解

    D - Subsequence POJ - 3061 <----------- 原题在这 题目大意 给定数组a,求其符合∑a[i] > S 的最短子数列. 尺取法解析 蒟蒻这道题WA了8次 ...

  4. 二叉查找树(一)之 图文解析 和 C语言的实现

    本文转载至http://www.cnblogs.com/skywang12345/p/3576328.html 二叉查找树(一)之 图文解析 和 C语言的实现 概要 本章先对二叉树的相关理论知识进行介 ...

  5. CF660C Hard Process(尺取法)

    整理的算法模板合集: ACM模板 尺取法 题目中要我们求最多改变k次后连续的1的最长长度.那么转换一下,不就是求至多包含k个0的子串的最长长度吗? 直接套用尺取法的思想,维护两端点,一旦0的个数超过k ...

  6. 【常用技巧精选】尺取法

    整理的算法模板合集: ACM模板 目录 1.反向扫描 1 找指定和的整数对 A.UVA1121 Subsequence B.POJ 3320 Jessica's Reading Problem C.l ...

  7. ACM—各种模拟 总结(字符串,尺取法,数学问题)习题汇总

    目录 一.字符串模拟 二. 高精度计算 1. 回文数(高精度,进制转换) 三.数学问题模拟 四.尺取法(双指针法) 1.都说小镇的切糕贵 (尺取法,字符串) umi和弓道 五.奇怪的模拟 x的位数=l ...

  8. 尺取法 POJ 3601 Subsequence

    题目传送门 1 /* 2 题意:求连续子序列的和不小于s的长度的最小值 3 尺取法:对数组保存一组下标(起点,终点),使用两端点得到答案 4 1. 记录前i项的总和,求[i, p)长度的最小值,用二分 ...

  9. poj2739(尺取法+质数筛)

    题意:给你一个数,问这个数能否等于一系列连续的质数的和: 解题思路:质数筛打出质数表:然后就是尺取法解决: 代码: #include<iostream> #include<algor ...

最新文章

  1. C++ Primer 第三版 读书笔记
  2. asp.net模糊查询存储过程
  3. Mint-UI 的 DatetimePicker 日期时间插件的安装与使用
  4. c int转char数组_C语言 指向数组和字符串的指针
  5. Jmeter5 语言中文
  6. Cisco2960交换机密码忘记恢复教程
  7. vuejs之v-if-ajax异步请求数据遇到的坑
  8. linux学习笔记:Linux 文件的基本属性
  9. 制作基于WiFi局域网的自动开门装置2.0(Arduino+微信小程序)
  10. 元转万元单位换算_excel中如何将元换算成万元 excel 万单位 不要万字
  11. pygame学习笔记——检测鼠标碰到、点击图片
  12. Linux 常用命令 一顿操作猛如虎
  13. android录音声波动画,Android开发:仿微信 录音声波
  14. 大道至简 知易行难 C# 完成WebSocket demo 用GoEasy实现Hello world
  15. dell服务器显示器接口在哪里,【Dell S2719H 显示器使用总结】安装|接口|边框|背板_摘要频道_什么值得买...
  16. Android适配全面总结(一)----屏幕适配
  17. windows文件读取 xxe_XXE任意文件读取(当xml解析内容有输出时)
  18. ycy支付宝和余额宝 DeBug
  19. 计算机课程设计答辩评语,【课程设计教师评语】_课程设计指导教师评语模板...
  20. 联想SR650服务器清除阵列配置信息

热门文章

  1. 设计师必备的导航网站
  2. NLP学习基础入门(上)
  3. 尚硅谷maven视频教程笔记
  4. ACME网站证书自动化保姆级教程
  5. 美通社企业新闻汇总 | 2019.1.10 | 全球最受欢迎商旅城市上海第四,华为发布AI数据中心交换机...
  6. php tcpdf 没有头部,TCPDF使用总结 - 从头笑到尾的个人空间 - OSCHINA - 中文开源技术交流社区...
  7. 微信支付:小微商户申请入驻第三步:平台证书序列号解密和敏感词加密
  8. openEuler虚拟机配置yum源
  9. java 不生成文件下载_java – 浏览器不生成文件下载对话框
  10. 烤鱼界头牌半天妖发文致歉,背后暴露了哪些问题?