题目链接:https://www.luogu.com.cn/problem/P1638

题目大意:

给你一个长度为 \(n (\le 10^6)\) 的数组,数组中每个元素的范围在 \(1\) 至 \(m\) 之间(\(1 \le m \le 2000\)),

求一个最短的连续子序列包含 \(1\) 到 \(m\) 内的所有元素。

解题思路:

这道题目我的解法是开一个队列,队列里面的元素是连续的。

那么怎么保证这个队列是连续的呢?

我只需要从 1 到 n 将每个元素入队,然后在需要的时候讲队首元素出队列。

但是不能单纯地入队出队。

我们开一个数组 \(c[i]\) 来表示第 \(i\) 位玩画家在队列中出现的次数,开一个变量 \(cnt\) 用于统计当前队列中有多少个不同的画家。

然后我们从 1 到 n 遍历 i ,对于每个 i,我们在令 \(a_i\) 入队的同时令 \(c[a_i] ++\) ,

此时若 \(c[a_i]\) 刚刚变为1,则说明编号为 \(a_i\) 的画家是第一次入队的,则我们令 \(cnt ++\) ,若此时 \(cnt\) 还没有等于 \(m\) ,说明还没有凑齐 \(m\) 个画家;

若此时 \(cnt == m\) 了,说明以第 \(i\) 个画家结尾的连续 que.size() 幅画凑成了 m 个画家。

但是这个时候并不一定是最优的结果,此时我们还要去判断:

如果当前队首元素对应的画家的画(假设为 \(a_j\) )出现的次数 \(\lt 1\) ,说明以 \(a_i\) 结尾的画去掉队列最前面的那副画也是能凑够 m 个画家的,那么我们就可以去掉队首的元素。

我们一直循环这样的操作指导队首元素不能出队列为止(即队首元素 \(a_j\) 对应的 \(c[a_j] == 0\) ,此时不能去掉它),此时的 que.size() 就是我们的一个备选答案。

我们的目的就是寻找所有备选答案中的最小值。

在这里我是使用队列queue来实现这个功能的。

我们也可以开两个指针(坐标)来解决这个问题,开两个指针的方法在国内被叫做尺取法,在国外被叫做“two points”,所以我就直接翻译成“双指针”了。

队列方式实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010, maxm = 2020;
int m, c[maxm], cnt, ans = INT_MAX, n, a[maxn], ans_a, ans_b;
queue<int> que;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) {
que.push(i);
c[ a[i] ] ++;
if (c[ a[i] ] == 1) cnt ++;
while (!que.empty() && c[ a[que.front()] ] > 1) {
c[ a[que.front()] ] --;
que.pop();
}
if (cnt == m && que.size() < ans) {
ans = que.size();
ans_a = que.front();
ans_b = que.back();
}
}
cout << ans_a << " " << ans_b << endl;
return 0;
}

洛谷P1638 逛画展 题解 尺取法/双指针/队列的更多相关文章

  1. 洛谷P1638 逛画展 (尺取法)

    尺取法的经典题目: 博览馆正在展出由世上最佳的 mm 位画家所画的图画. 游客在购买门票时必须说明两个数字,aa 和 bb,代表他要看展览中的第 aa 幅至第 bb 幅画(包含 a,ba,b)之间的所 ...

  2. 洛谷 P1638 逛画展 题解

    P1638 逛画展 题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字, ...

  3. [洛谷P1638]逛画展

    [洛谷P1638]逛画展 题目大意: 有\(n(n\le10^6)\)个格子,每个格子有一种颜色.颜色种数为\(m(m\le2000)\).求包含所有颜色的最小区间. 思路: 尺取法裸题. 思路: # ...

  4. 洛谷P1638逛画展

    传送门啦 只需记录满足条件的一个区间的初始端点 $ (head, tail) $ ,不断删掉左端点 $ head $ ,不断更新右端点 $ tail $ : 开一个 $ vis[] $ 记录一下每幅画 ...

  5. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  6. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  7. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  8. 洛谷P1577 切绳子题解

    洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

随机推荐

  1. Python基础:常用函数

    1:enumerate enumerate(sequence, start=0) 该函数返回一个enumerate对象(一个迭代器).其中的sequence参数可以是序列.迭代器或者支持迭代的其他对象 ...

  2. 首次揭秘:阿里巴巴中间件在 Serverless 技术领域的探索

    Serverless 话题涉及范围极广,几乎包含了代码管理.测试.发布.运维和扩容等与应用生命周期关联的所有环节.AWS Lambda 是 Serverless 领域的标志性产品,但如果将其应用于核心 ...

  3. php 第三方登录总结OAuth协议

  4. visual studio 2013 修改mvc5的视图模板

    C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffol ...

  5. C#的循环语句(四)

    一.while 循环(1).while 其实是for循环的变形写法for(int i = 1; i<=5;i++)  {循环体:} 上面的for循环可以写成int i= 1:for(;i< ...

  6. JS精度问题,解决方案 math.js

    JS精度问题    Vue中使用 解决方案 math.js npm install mathjs import { create, all } from 'mathjs' const config = ...

  7. java引用变量类型转换

    向上转型(子类→父类):(自动完成) 父类名称 父类对象 = 子类实例 ; 向下转型(父类→子类):(强制完成) 子类名称 子类对象 = (子类名称)父类实例 ; 对象名   instanceof  ...

  8. SVN中如何执行clean up

    在要清理的文件夹上点右键,菜单:TortoiseSVN--选择cleanup,会出现一个菜单栏,在你菜单栏有一个属性breaklock意思是打破锁定,你勾选打破锁定,然后cleanup就会成功,之后再 ...

  9. int64 DWORD 与cstring 互转

    //int64 与cstring 互转 int64_t val = 1111111111111111111; CString str; str.Format(("%I64d"), ...

  10. liunx重定向控制台消息

    Linux 在控制台记录策略上允许一些灵活性, 它允许你发送消息到一个指定的虚拟控制台 (如果你的控制台使用的是文本屏幕). 缺省地, 这个"控制台"是当前虚拟终端. 为了选择 一 ...