单调队列问题
来源:互联网 发布:将js文件引入html代码 编辑:程序博客网 时间:2024/06/18 09:53
Sliding Window
题目传送:POJ - 2823 - Sliding Window
闲来没事学学单调队列的写法,嗯,一个很奇怪的队列形式。。
单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。
因为这里是滑动窗口,每次移动需要进行更新,所以可以用单调队列来实现。
本题用单调递增队列来求每一个区间的最小值,用单调递减队列来求每一个区间的最大值,用一个pos数组记录单调队列里每一个数出现的位置来比较是否要更新(即删去)
具体实现还是看代码吧。
AC代码:
#include <map>#include <set>#include <list>#include <cmath>#include <deque>#include <queue>#include <stack>#include <bitset>#include <cctype>#include <cstdio>#include <string>#include <vector>#include <complex>#include <cstdlib>#include <cstring>#include <fstream>#include <sstream>#include <utility>#include <iostream>#include <algorithm>#include <functional>#define LL long long#define INF 0x7fffffffusing namespace std;const int maxn = 1000005;int a[maxn];int Min[maxn];//记录每个窗口最小答案int Max[maxn];//记录每个窗口最大答案int que[maxn];//数组模拟单调队列int pos[maxn];//记录位置,用来更新int n, k;void get_min() {//维护单调递增队列,队头为最小 int head = 0, rear = 0; for(int i = 1; i < k; i ++) {//先将前k-1个放入队列 while(rear > head && que[rear - 1] > a[i]) rear --; que[rear] = a[i]; pos[rear] = i; rear ++; } for(int i = k; i <= n; i ++) { while(rear > head && que[rear - 1] > a[i]) rear --; que[rear] = a[i]; pos[rear] = i; rear ++; while(pos[head] < i - k + 1) head ++;//因为是滑窗,所以要及时更新 Min[i] = que[head]; }}void get_max() {//维护单调递减队列,队头为最大 int head = 0, rear = 0; for(int i = 1; i < k; i ++) {//先将前k-1个放入队列 while(rear > head && que[rear - 1] < a[i]) rear --; que[rear] = a[i]; pos[rear] = i; rear ++; } for(int i = k; i <= n; i ++) { while(rear > head && que[rear - 1] < a[i]) rear --; que[rear] = a[i]; pos[rear] = i; rear ++; while(pos[head] < i - k + 1) head ++;//因为是滑窗,所以要及时更新 Max[i] = que[head]; }}int main() { while(scanf("%d %d", &n, &k) != EOF) { for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); } get_min(); get_max(); for(int i = k; i < n; i ++) { printf("%d ", Min[i]); } printf("%d\n", Min[n]); for(int i = k; i < n; i ++) { printf("%d ", Max[i]); } printf("%d\n", Max[n]); } return 0;}
Subsequence
题目传送:HDU - 3530 - Subsequence
AC代码:
#include <map>#include <set>#include <list>#include <cmath>#include <deque>#include <queue>#include <stack>#include <bitset>#include <cctype>#include <cstdio>#include <string>#include <vector>#include <complex>#include <cstdlib>#include <cstring>#include <fstream>#include <sstream>#include <utility>#include <iostream>#include <algorithm>#include <functional>#define LL long long#define INF 0x7fffffffusing namespace std;const int maxn = 100005;int n, m, k;int a[maxn];int q1[maxn], q2[maxn];//单调队列记录最大和最小的位置int head1, rear1;int head2, rear2;int main() { while(scanf("%d %d %d", &n, &m, &k) != EOF) { head1 = rear1 = 0; head2 = rear2 = 0; int pre = 1;//记录可行区间的最左,i可以动态表示可行区间的最右 int ans = 0; for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); while(rear1 > head1 && a[q1[rear1 - 1]] < a[i]) rear1 --; while(rear2 > head2 && a[q2[rear2 - 1]] > a[i]) rear2 --; q1[rear1 ++] = i; q2[rear2 ++] = i; while(rear1 > head1 && rear2 > head2 && a[q1[head1]] - a[q2[head2]] > k) {//更新可行区间的最左 if(q1[head1] > q2[head2]) pre = q2[head2 ++] + 1; else pre = q1[head1 ++] + 1; } if(rear1 > head1 && rear2 > head2 && a[q1[head1]] - a[q2[head2]] >= m) {//此区间的最大最小满足在m,k之间,所以更新答案 ans = max(ans, i - pre + 1);//更新答案 } } printf("%d\n", ans); } return 0;}
0 0
- 单调队列问题
- 线性 dp问题の 单调队列优化
- 单调队列之广告印刷问题
- 单调队列之烽火传递问题
- 【BZOJ1342】【Baltic2007】Sound静音问题 单调队列
- dp的单调队列优化问题
- POJ--2823--Sliding Window----单调队列问题
- 单调栈 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- linux基础笔记
- Java断言Assert的使用以及在Eclipse中使用assert
- 什么是堆和栈,它们在哪儿?
- 在Java静态方法中获取当前类名
- Android SQLite数据库应用之基本介绍
- 单调队列问题
- 小白学习iOS开发都需要有什么基础
- define与typedef
- getrlimit和setrlimit函数 设置资源权限
- Get data from local via pandas
- C#开发ActiveX控件
- 关于算法的时间复杂度的探讨
- cocos2d-x 3.0 (vs2012环境下亲测)把json数据转换成unicode编码来传送用户数据并且实现json数据的解析和封装
- C++ Primer : 第十三章 : 拷贝控制之对象移动