单调队列
2011-06-17 21:46
381 查看
单调队列 : 队列中保存的是潜在的解,队首保存最优解。
支持操作 : 与普通队列支持的操作相同,push_back() , pop()。
pop()操作仅仅返回队首元素, 因此时间复杂度O(1)。
push_back()操作,均摊下来每次操作的时间复杂度O(1):1.消除所有不可能的解 2.更新队首指针使其指向最优解
http://poj.org/problem?id=2823
题意 : 有一个窗口,让其从数组的最左端移动到最右端,求每次移动后窗口中的最大值与最小值。
支持操作 : 与普通队列支持的操作相同,push_back() , pop()。
pop()操作仅仅返回队首元素, 因此时间复杂度O(1)。
push_back()操作,均摊下来每次操作的时间复杂度O(1):1.消除所有不可能的解 2.更新队首指针使其指向最优解
http://poj.org/problem?id=2823
题意 : 有一个窗口,让其从数组的最左端移动到最右端,求每次移动后窗口中的最大值与最小值。
// 2823 Moving Window.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; bool comp_for_max( const int newAppear, const int rear ) { // Max MonQueue return newAppear >= rear; } bool comp_for_min( const int newAppear, const int rear ) { // Min MonQueue return !(newAppear >= rear); } /* * 单调队列模板 * 建议单调队列大小与数组相同 */ struct MonQueue { // 数据 int* q; int top, rear, winLen; bool is_empty; // 构造与析构 MonQueue( const int n, const int winLen ) { q = new int ; top = rear = 0; this->winLen = winLen; // 窗体长度 is_empty = true; // 初始化为空 } ~MonQueue( void ) { delete [] q; } // 操作 /* * 功能 : 将a[index]添加进单调队列 * 参数 : a[] in, 被添加元素所在数组 * index in, 被添加元素的下标 * comp in, 函数指针,用于实现单调队列的单调性 * 返回 : 无 */ void Push_Back( int a[], int index, bool (*comp)(const int,const int) ) { // 添加 if( is_empty ) { q[top] = index; is_empty = false; return; } while( top <= rear && comp(a[index],a[q[rear]]) ) -- rear; q[ ++rear ] = index; // 更改队首 while( index - q[top] >= winLen ) ++ top; } /* * 功能 : 获取队首元素下标 */ int Pop( void ) { return q[top]; } }; // 对象 int a[1000000], len; int winLen; // 窗体长度 MonQueue *qMax, *qMin; // 最大,最小单调队列 int res1[1000000], res2[1000000]; int main() { while( scanf( "%d%d", & len, & winLen ) != EOF ) { for( int i = 0; i < len; ++ i ) scanf( "%d", & a[i] ); MonQueue* qMax = new MonQueue( len, winLen ); MonQueue* qMin = new MonQueue( len, winLen ); // 初始化第一个窗口 for( int i = 0; i < winLen; ++ i ) { qMax->Push_Back( a, i, comp_for_max ); qMin->Push_Back( a, i, comp_for_min ); } res1[0] = a[ qMax->Pop() ]; res2[0] = a[ qMin->Pop() ]; // 移动窗口 for( int i = winLen; i < len; ++ i ) { qMax->Push_Back( a, i, comp_for_max ); qMin->Push_Back( a, i, comp_for_min ); res1[ i-winLen+1 ] = a[ qMax->Pop() ]; res2[ i-winLen+1 ] = a[ qMin->Pop() ]; } // 打印 for( int i = 0; i < len - winLen + 1; ++ i ) printf( "%d ", res2[i] ); // 先打印窗口中的最小值 cout << "/n"; for( int i = 0; i < len - winLen + 1; ++ i ) printf( "%d ", res1[i] ); // 打印窗口中的最大值 cout << "/n"; delete qMax; delete qMin; } system( "pause" ); return 0; }
相关文章推荐
- bzoj1999 [Noip2007]Core树网的核(树的直径+单调队列+贪心)
- hdu3530单调队列(双)
- hdu 4123 Bob’s Race (树的直径相关+rmq+单调队列思想)
- BSOJ3068 BZOJ2500 noip模拟赛 幸福的道路 树的最长链+单调队列 或 RMQ
- HDU 3410 && POJ 3776 Passing the Message 单调队列
- Sliding Window poj2823--单调队列
- POJ 2823 Sliding Window 单调队列题解
- 【poj1821】Fence 单调队列优化DP
- POJ 2823 Sliding Window(单调队列)
- hdu 2191(单调队列优化多重背包模板)
- 【poj】 2823 Sliding Window 单调队列
- BZOJ 4721 [Noip2016]蚯蚓 单调队列
- [bzoj1047][HAOI2007]理想的正方形【单调队列】
- poj3614 Sunscreen 贪心+单调队列
- POJ2796 单调队列
- HDOJ 5289 Assignment 单调队列
- 假期(动态规划+单调队列)
- 窗口(单调队列)
- fzu 1894 志愿者选拔(单调队列)
- 单调队列优化多重背包