单调队列实现与例题
来源:互联网 发布:淘宝怎么看卖家信用 编辑:程序博客网 时间:2024/06/06 08:57
单调队列
就是一个符合单调性质的队列,它同时具有单调的性质以及队列的性质。他在编程中使用频率不高,但却占有至关重要的地位。它的作用很简单,就是为了维护一组单调数据,让我们在运行的过程中能够快速寻求前k个或后k个中最大或最小的值。
单调队列的核心就是队列中的元素保持递增或递减
强行证明正确性:
对于最大数的操作
假设在数组 a 中存在某个数 x , 它在以它为中心, 长度为 2*k-1 的区间中是最大的, 也就是说, 往前 k-1 个数, 往后 k-1 个数, 都小于或等于 x;
例如: 2 3 4 5 2 3 4 (k=4)
先讨论 2*k-1 区间中没有等于 x 的数的情况
当 push(x) 时
- 若队列中存在比 x 大的数, 那么它在数组中的位置距离 x 一定大于 k (由假设可知), 所以它会从队首出队
- 这时队列中存在的数都小于 x , 执行 push(x) 就表示长度为 k 的区间已经覆盖了 x , 在 x 出队前, 它一定是所求的值(由假设可知), 所以队列中的数会全部从队尾出队
- 执行之后 队列中就只剩 x 一个元素
然后是 2*k-1 区间中 x 前面存在一个等于 x 的数 y 的情况
当 push(x) 时
- 如果队列中 y 出队, 并将 x 入队, 由于 x 与 y 的值相等, 得到的结果与更新 y 对应的时间戳为 x 的时间戳等价, 所以可以将其出队(事实上不出队也不会对正确性有影响)
2*k-1 区间中 x 后面存在一个等于 x 的数 y 的情况
与上一种情况类似
对于其他数
写不下去了
裸题欣赏:
COGS495 窗口
★☆ 输入文件:window.in 输出文件:window.out 简单对比
时间限制:2 s 内存限制:256 MB
问题描述
给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的 max value, min value.
输入格式
第一行 n,k,第二行为长度为n的数组
输出格式
第一行每个位置的 min value, 第二行每个位置的 max value
样例
输入
8 3
1 3 -1 -3 5 3 6 7
输出
-1 -3 -3 -3 3 3
3 3 5 5 6 7
数据范围
20%:n≤500;
50%:n≤100000;
100%:n≤1000000;
两个单调队列,一个计算最大,一个计算最小
代码实现
#include <cstdio> const int N = 1000000+10; struct P{ int x, t;//x 是值, t 是时间戳 }; P Max_que[N], Min_que[N]; int Max_head = 0, Max_tail = 0, Min_head = 0, Min_tail = 0; int a[N]; int n, k; inline void Max_push(int x, int t){ while(Max_head > Max_tail && Max_que[Max_tail].t < t-k+1)Max_tail++;//已经不包含在长为 k 的块的数出队 while(Max_head > Max_tail && Max_que[Max_head-1].x < x)Max_head--;//比将要入队的书小的数出队 Max_que[Max_head++] = (P){x, t}; }inline void Min_push(int x, int t){ while(Min_head > Min_tail && Min_que[Min_tail].t < t-k+1)Min_tail++; while(Min_head > Min_tail && Min_que[Min_head-1].x > /*只有这里和上面不一样*/ x)Min_head--; Min_que[Min_head++] = (P){x, t}; }inline int getint(int ret = 0, char c = getchar(), bool neg = 0){//快速读入, 参数是为了压行 while(c < '0' || c > '9')c = getchar(),if(c == '-')neg = true; while(c >= '0'&&c <= '9')ret = ret*10+c-'0', c = getchar(); return neg ? -ret : ret; }inline void putint(int x){//快速输出 int i = 1; char put[15] if(x < 0)x = -x,putchar('-');//处理负数 if(x == 0)putchar('0'); while(x) put[i++] = x%10+'0', x/ = 10; i--; while(i > 0)putchar(put[i--]); }int main(){ freopen("window.in","r",stdin); freopen("window.out","w",stdout); scanf("%d%d", &n, &k); for(int i = 0; i < n; i++)a[i] = getint(); for(int i = 0; i < k-1; i++)Min_push(a[i], i);//把前面的先加入队列,注意边界是 i < k-1 for(int i = k-1; i < n; i++){//每次加入都输出一次 Min_push(a[i], i); putint(Min_que[Min_tail].x); putchar(' '); } putchar('\n'); //重复上面的操作, 差别不大 for(int i = 0; i < k-1; i++)Max_push(a[i], i); for(int i = k-1; i < n; i++){ Max_push(a[i], i); putint(Max_que[Max_tail].x); putchar(' '); } return 0; }
0 0
- 单调队列实现与例题
- Sliding Window(单调队列讲解与例题)
- 单调队列的实现与应用
- 【例题】【单调队列】NKOJ2150 广告印刷
- 单调队列与单调栈
- 单调栈与单调队列
- 栈与队列-单调栈,单调队列
- 用双端队列实现单调队列
- 单调队列与DP
- 单调队列与单调栈总结
- 单调队列与单调栈用法详解
- 单调队列典型例题——广告印刷
- 【例题&结论】【单调队列(滑动窗口)】NKOJ2152 滑动窗口
- 【例题】【单调队列优化DP】NKOJ2151 烽火传递
- hdu1506(单调队列实现)
- 【跳棋、跳房子】与单调队列
- 单调栈和单调队列的概念与运用
- 单调栈及单调队列基础与运用
- atitit.错误:找不到或无法加载主类 的解决 v4 qa15.doc
- 关于新用户第一次赠送金额的处理
- Ajax详解及其案例分析------如何获得Ajax对象,使用Ajax对象发送GET和POST请求,校验用户名,POST和GET请求时的乱码处理,实现级联的下拉列表
- java接口的一些小知识
- 面向对象的三大特性
- 单调队列实现与例题
- Linux下编写支持多线程的库
- Mysql 内连接、外连接、全连接和交叉连接
- jQuery UI 实例 - 自动完成(Autocomplete)
- Atitit RSA非对称加密原理与解决方案
- Swift中的required修饰符
- Codeforce 723A - The New Year: Meeting Friends
- Weiss-(DSAA - in C,2.12)最大子序列求和
- MySQL 之 count(*) 与 count(1)