很早看過這個東西,不過今天遇到一道題發現居然沒有寫筆記。。。這裡補上吧。
以下是我從某個題的解題報告翻出來的。轉載的別人的。。。。
以此為例:對於N=8,K=3,8個元素序列1 3 -1 -3 5 3 6 7,視窗大小為3,也就是要求出(1, 3, -1), (3, -1, -3), (-1, -3, 5), (-3, 5, 3), (5, 3, 6), (3, 6, 7)這6個序列中的最小值,結果簡單,就是-1, -3, -3, -3, 3, 3.
使用單調隊列,首先要有一個資料結構
struct node { int seq, val; }
用於記錄隊列中的元素及其在輸入序列中的順序。隊列的狀態是這樣維護的:
1: [0, 1] //隊列空,[seq=0, val=1]入隊
3: [0, 1], [1, 3] //3大於隊尾元素,放在隊尾
-1: [2, -1] //從隊尾往前掃,-1小於每一個所有元素,於是把它們都T掉
-3: [3, -3] //-3把-1T掉
5: [3, -3], [4, 5] //入隊尾
3: [3, -3], [5, 3] //把隊尾的5T掉
6: [5, 3], [6, 6] //隊首元素seq=3太老了,T掉;6比3小,放在隊尾
7: [5, 3], [6, 6], [7, 7] //入隊尾
從以上的處理方法可以看出:最老的元素要麼早就被T掉了,要麼就是最小的元素(排在隊首)。所以每次加入一個新元素的時候:
1. 把需要出隊的隊首元素T掉;
2. 把隊尾大於或等於它的元素全部T掉,自己入隊。
說白了就是是保證視窗的元素的value是從前往後是依次減小(增大)的。還有一個值就是當前value的position,也就是說視窗裡所有元素 的position都必須跟當前待插入的元素的position的距離相差小於等於視窗的大小。(-_-! 說的好彆扭)
今天補補模板吧。。。。
class Node {public: int pos; int val; Node() {}; Node(int _a, int _b) : pos(_a), val(_b) {}};class Dequ{ Node deq[N];public: void Get_Min(int ans[], int _num[], int n, int k) { int i, head, tail; head = tail = 0; REP(i, n) { if(head < tail && deq[head].pos <= i - k) head++; while(head < tail && deq[tail-1].val >= _num[i]) tail--; deq[tail++] = Node(i, _num[i]); ans[i] = deq[head].val; } } void Get_Max(int ans[], int _num[], int n, int k) { int i, head, tail; head = tail = 0; REP(i, n) { if(head < tail && deq[head].pos <= i - k) head++; while(head < tail && deq[tail-1].val <= _num[i]) tail--; deq[tail++] = Node(i, _num[i]); ans[i] = deq[head].val; } }} Dequeue;