[单调队列] POJ2823
2017-09-09 17:22
148 查看
找出范围内的最大和最小
第一次接触单调队列(保证队列单调性)
放一下方法(因为明天一定会忘光光的hhh)
开始很不理解为什么队列要把比新插入的数小的数全部删除
但这道题只要最大值就没追究了
也是能保持头部的index永远是最小的一个关键
判断改成head<=end 后就不是WA了
但g++还是TLE,C++是AC
参考:http://blog.csdn.net/justmeh/article/details/5844650
假设数列为:8,7,12,5,16,9,17,2,4,6.N=10,k=3.
那么我们构造一个长度为3的单调递减队列:
首先,那8和它的索引0放入队列中,我们用(8,0)表示,每一步插入元素时队列中的元素如下:
0:插入8,队列为:(8,0)
1:插入7,队列为:(8,0),(7,1)
2:插入12,队列为:(12,2)
3:插入5,队列为:(12,2),(5,3)
4:插入16,队列为:(16,4)
5:插入9,队列为:(16,4),(9,5)
1.首先看插入元素:为了保证队列的递减性,我们在插入元素v的时候,要将队尾的元素和v比较,如果队尾的元素不大于v,则删除队尾的元素,然后继续将新的队尾的元素与v比较,直到队尾的元素大于v,这个时候我们才将v插入到队尾。
2.队尾的删除刚刚已经说了,那么队首的元素什么时候删除呢?由于我们只需要保存i的前k-1个元素中的最大值,所以当队首的元素的索引或下标小于i-k+1的时候,就说明队首的元素对于求f(i)已经没有意义了,因为它已经不在窗里面了。所以当index[队首元素]<i-k+1时,将队首元素删除。
第一次接触单调队列(保证队列单调性)
放一下方法(因为明天一定会忘光光的hhh)
开始很不理解为什么队列要把比新插入的数小的数全部删除
但这道题只要最大值就没追究了
也是能保持头部的index永远是最小的一个关键
判断改成head<=end 后就不是WA了
但g++还是TLE,C++是AC
参考:http://blog.csdn.net/justmeh/article/details/5844650
假设数列为:8,7,12,5,16,9,17,2,4,6.N=10,k=3.
那么我们构造一个长度为3的单调递减队列:
首先,那8和它的索引0放入队列中,我们用(8,0)表示,每一步插入元素时队列中的元素如下:
0:插入8,队列为:(8,0)
1:插入7,队列为:(8,0),(7,1)
2:插入12,队列为:(12,2)
3:插入5,队列为:(12,2),(5,3)
4:插入16,队列为:(16,4)
5:插入9,队列为:(16,4),(9,5)
1.首先看插入元素:为了保证队列的递减性,我们在插入元素v的时候,要将队尾的元素和v比较,如果队尾的元素不大于v,则删除队尾的元素,然后继续将新的队尾的元素与v比较,直到队尾的元素大于v,这个时候我们才将v插入到队尾。
2.队尾的删除刚刚已经说了,那么队首的元素什么时候删除呢?由于我们只需要保存i的前k-1个元素中的最大值,所以当队首的元素的索引或下标小于i-k+1的时候,就说明队首的元素对于求f(i)已经没有意义了,因为它已经不在窗里面了。所以当index[队首元素]<i-k+1时,将队首元素删除。
#include <cstdio> #include <cstring> #include <iostream> #define N 3500000 using namespace std; int n, k; int Num[ N ]; //输入 struct Node { int val, idx; } Que[ N ]; void GetMax () { memset ( Que, 0, sizeof ( Que ) ); int head = 0; //保存头部位置 int end = -1; //保存尾部位置 for ( int i = 1; i <= n; i++ ) { Node tmp; tmp.val = Num[ i ]; tmp.idx = i; while ( head <= end && Que[ end ].val <= Num[ i ] ) // 1.去掉尾部比新加入元素小的 end--; Que[ ++end ] = tmp; while ( head <= end && Que[ head ].idx < i - k + 1 ) // 2.去掉头部index超过范围的 head++; if ( i >= k ) { if ( i != k ) printf ( " " ); printf ( "%d", Que[ head ] ); } } printf ( "\n" ); } void GetMin () { memset ( Que, 0, sizeof ( Que ) ); int head = 0; int end = -1; for ( int i = 1; i <= n; i++ ) { Node tmp; tmp.val = Num[ i ]; tmp.idx = i; while ( head <= end && Que[ end ].val >= Num[ i ] ) end--; Que[ ++end ] = tmp; while ( head <= end && Que[ head ].idx < i - k + 1 ) head++; if ( i >= k ) { if ( i != k ) printf ( " " ); printf ( "%d", Que[ head ] ); } } printf ( "\n" ); } int main () { while ( cin >> n && cin >> k ) { for ( int j = 1; j <= n; j++ ) scanf ( "%d", &Num[ j ] ); GetMin (); GetMax (); } return 0; }
相关文章推荐
- POJ2823 Sliding Window(单调队列)
- Poj2823 Sliding Window (单调队列)
- poj2823 单调队列 ------scanf/printf/G++/C++
- POJ2823 Sliding Window(单调队列模版题)
- poj2823单调队列(模拟优先队列)
- POJ2823 线段树OR单调队列
- POJ2823(单调队列初步)
- poj2823--Sliding Window--线段树||单调队列
- POJ2823 单调队列
- POJ2823:Sliding Window(单调队列||线段树)
- poj2823,典型的单调队列
- POJ2823 Sliding Window,手工实现单调队列
- POJ2823 滑动窗口中元素的最值(单调队列)
- POJ2823 - Sliding Window - 单调队列
- POJ2823 单调队列优化入门
- 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
- poj2823 Sliding Window(单调队列)
- 单调队列经典题目 poj2823
- 单调队列 poj2823,fzu1894
- 单调队列 poj2823 Sliding Window