Monotone Queue - 单调队列


https://blog.csdn.net/A_Bright_CH/article/details/77076228
使用单调队列就涉及到去头和删尾:

1、队列的头一定是在一段时间前就加入了队列,现在的队列头会不会离开了我们处理的区间呢?如果它离我们正在处理的i太远了,我们就要把它去掉,去除冗杂的信息。

2、为了保证队列的递减性,在从列队尾新插入元素v时,要考虑队列尾的值是否大于v,如果是,队列呈现 队列尾-1的值 > 队列尾的值 > v ,此时队列递减性没有消失;如果不是,队列呈现 队列尾-1的值 > 队列尾的值 < v ,队列递减性被打破。

为了维护递减性,我们做如下考虑:v是最新值,它的位置是目前最靠后的,它可成为以后的最大值,必须留下;队列尾-1的值与v大小不定,不能冒然删去它;队列尾的值夹在v和队列尾-1之间,它不但不是最大值,对于以后的情况又不如v优,因为v相比队列尾更靠后(v可以影响到后m个值,队列尾只能影响到从它的位置往后数m-1个值),而且值更大,所以删队列尾是必定的。



在维护好一个 区间正确、严格递减 的单调递减队列后,队列头就是当前区间的最大值了。

整理归纳单调队列的定义:

1、维护区间最值;
2、去除冗杂状态;
3、保持队列单调(最大值是单调递减序列,最小值是单调递增序列);
4、最优选择在队首。



整理归纳单调队列的使用方法:

1、维护队首(对于上题就是如果你已经是当前的m个之前那你就可以被删了) ;
2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态) ;
3、取出需要的最优解(队列头的值即是);
4、借助最优解,得到目前所求的最优解(通常此处插入DP方程)。



单调队列的原理:

在处理f[i]时,去除冗杂、多余的状态,使得每个状态在队列中只会出现一次;同时维护一个能瞬间得出最优解的队列,减少重新访问的时间;在取得自己所需的值后,为后续的求解做好准备。

https://www.cnblogs.com/neverforget/archive/2011/10/13/ll.html
    单调队列,望文生义,就是指队列中的元素是单调的。如:{a1,a2,a3,a4……an}满足a1<=a2<=a3……<=an,a序列便是单调递增序列。同理递减队列也是存在的。
    单调队列的出现可以简化问题,队首元素便是最大(小)值,这样,选取最大(小)值的复杂度便为o(1),由于队列的性质,每个元素入队一次,出队一次,维护队列的复杂度均摊下来便是o(1)。
如何维护单调队列呢,以单调递增序列为例:
1、如果队列的长度一定,先判断队首元素是否在规定范围内,如果超范围则增长队首。
2、每次加入元素时和队尾比较,如果当前元素小于队尾且队列非空,则减小尾指针,队尾元素依次出队,直到满足队列的调性为止
要特别注意头指针和尾指针的应用。
单调队列的应用仍有很多实例,这一不能一一道出。
   首先考虑问题需要的时间复杂度如果是o(n)的算法,单调队列是首选。
   其次要善于观察分析,发现题目中的单调性。决策的单调(合并果子),要求问题的特性(window),元素价值和其在原序列中位置的单调(志愿者),问题结果的单调(广告印刷)。

https://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html
单调队列是一种严格单调的队列,可以单调递增,也可以单调递减。队首位置保存的是最优解,第二个位置保存的是次优解,ect。。。

单调队列可以有两个操作:
1、插入一个新的元素,该元素从队尾开始向队首进行搜索,找到合适的位置插入之,如果该位置原本有元素,则替换它。
2、在过程中从队首删除不符合当前要求的元素。

单调队列实现起来可简单,可复杂。简单的一个数组,一个head,一个tail指针就搞定。复杂的用双向链表实现。

用处:
1、保存最优解,次优解,ect。
2、利用单调队列对dp方程进行优化,可将O(n)复杂度降至O(1)。也就是说,将原本会超时的N维dp降优化至N-1维,以求通过。这也是我想记录的重点
是不是任何DP都可以利用单调队列进行优化呢?答案是否定的。
记住!只有形如 dp[i]=max/min (f[k]) + g[i]  (k<i && g[i]是与k无关的变量)才能用到单调队列进行优化。
优化的对象就是f[k]。

https://blog.csdn.net/zhjchengfeng5/article/details/7653120
单调队列很好理解,就是一个双向队列,队首队尾允许删除操作,队尾进行添加操作,维护整个队列的严格单调性,即队列中不存在相等的元素(这样时间常数小一点)。

那么用单调队列优化的DP应该具有怎样的性质呢?

假如我们有下面的DP转移方程:

    f[i] = min( f[j] ) + a[i]

那么当 j 满足一个条件: Low[i] <= j <= Up[i] ,这里的 Low 和 Up 是关于 i 的单调函数,而且是单调递增的,为什么呢?联系经典的单调队列入门题: Sliding Window 想想就清楚了: 当我用下一个 Low[i] 的时候,Low[i] 必须大于等于 Low[i-1] ,因为队首涉及到了要出队列的操作,而队尾的元素上界: Up 也是必须具有单调递增的性质,因为再用队尾的元素的时候,涉及到添加元素的操作。如果还是不很明白,那么联系 Sliding Window 仔细想想这个单调队列删除插入的过程即可。很好想通的。


https://oi.men.ci/monotone-queue-notes/
单调队列,就是单调的队列,通常用来解决滑动窗口的最值问题,可以应用到 DP 的优化上。一个单调队列中的元素总是单调递增(或递减)的。

滑动窗口

例:有一个队列,每次从队尾加入一个元素,或从队首删除一个元素,并在任何时刻求整个队列的最大值。
一个很直接的想法是使用优先队列 priority_queue 即堆,堆可以在 O(1) 的时间内求出最大值,但每次加入或删除时需要 O({\log}n) 的时间完成堆的调整,但是用了堆后就不能按照进队的顺序出队了!这时候你可以大胆地写一个平衡树或者 set——如果你不怕多出来的 \log 和平衡树常数带来的 TLE 的话。

单调队列就是解决这类问题的数据结构,我们用一个辅助队列,使该队列的首元素总是原队列的最大值,这样就可以 O(1) 地求出队列的最大值了。

维护单调队列

现有需要维护最大值的队列 Q,和辅助队列 M,设计算法使任何时刻时 M 队首元素都是当前 Q 的最大值。
每次在 Q 的队尾加入元素 x 时,也将其加入到 M 中,从 M 的队尾向前遍历,将遍历到的所有 小于等 x 的元素全部删除,因为它们在 x 之前被加入到队列中,在 x 出队前它们就已经都出队了,即在 x 出队前这些元素不可能成为队列中的最大值
每次在 Q 的队首删除元素时,将要删除的元素与 M 的队首元素比较,如果该元素与 M队首元素相等,即该元素为执行删除操作前队列的最大值,则同时也要将 M 的队首元素删除,使原 Q 的次小值成为 M 的队首元素,保证 M 的队首元素是删除操作后 Q 中最大的元素。

应用

状态转移方程形如 f[x]=\max\{g(k)\}+w[x] 的动态规划可以使用单调队列来优化。

实现

因为同时要从队列的两端添加、删除,所以要使用 deque 实现,而不是 queue
template <typename T>
struct MonotoneQueue {
    std::deque<T> q, m;

    void push(const T &x) {
        q.push_back(x);
        while (!m.empty() && m.back() < x) m.pop_back();
        m.push_back(x);
    }

    void pop() {
        T x = q.front();
        q.pop_front();
        if (x == m.front()) m.pop_front();
    }

    size_t size() {
        return q.size();
    }

    T top() {
        return m.front();
    }
};




Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts