洛谷 P1886 滑动窗口(单调队列)

题目原网址:https://www.luogu.org/problemnew/show/P1886

解题思路:

维护一个单调队列,

假如我们先求最小值,保证队首就是最小值,满足滑动窗口长度时输出队首;

例如样例 1 3 -1 -3 5 3 6 7

第一步 1 先入队了

第二步  1 小于3 没问题 所以3接着入队了

第三步   1和3 都大于-1 所以1和3都弹出  -1入队  此时刚好满足长度为k(k=3)的滑动窗口,输出队首 -1

第四步  -1 大于 -3 所以-1弹出 -3 入队  输出队首-3

第五步 -3 小于5 没问题  5入队 输出队首-3

第六步  5大于3  那5不论怎么样都不可能是最小值了,所以弹出5  ,3入队,输出队首-3

第六步  3小于6没问题  6入队,此时滑动窗口覆盖范围已经走到了(5,3,6) 所以要将-3 出队,输出队首3

第七步 6小于7没问题   ,7入队,输出队首3

 求最大值的话同理

//以上转载自:https://www.cnblogs.com/llke/p/10780121.html

AC代码:

  1 #include<cstdio>
  2 #include<queue>
  3 #include<iostream>
  4 
  5 using namespace std;
  6 
  7 deque<int> l;
  8 queue<int> _min,_max;
  9 int n,k,num[1000001];
 10 
 11 void findmin() {
 12     int minid = 1,o,minn = 0x7f7f7f,ts;
 13     for(int i = 1;i <= k; i++) {
 14         if(l.empty()) 
 15             l.push_back(i);
 16         o = num[i];
 17         if(o <= minn) {
 18             minn = o;
 19             minid = i;
 20             while(!l.empty()) {
 21                 o = l.front();
 22                 if(num[o] >= minn) 
 23                     l.pop_front();
 24                 else break;
 25             }
 26             l.push_front(minid);
 27         }
 28         else {
 29             while(!l.empty()) {
 30                 o = l.back();
 31                 if(num[o] >= num[i]) 
 32                     l.pop_back();
 33                 else break;
 34             }
 35             l.push_back(i);
 36         }
 37     }
 38     _min.push(minn);
 39     for(int i = k + 1;i <= n; i++) {
 40         if(minid <= i - k) {
 41             l.pop_front();
 42             minid = l.front();
 43             minn = num[minid];
 44         }
 45         if(l.empty()) l.push_back(i);
 46         o = num[i];
 47         if(o <= minn) {
 48             minn = o;
 49             minid = i;
 50             while(!l.empty()) {
 51                 o = l.front();
 52                 if(num[o] >= minn)
 53                     l.pop_front();
 54                 else break;
 55             }
 56             l.push_front(minid);
 57         }
 58         else {
 59             while(!l.empty()) {
 60                 o = l.back();
 61                 if(num[o] >= num[i]) 
 62                     l.pop_back();
 63                 else break;
 64             }
 65             l.push_back(i);
 66         }
 67         _min.push(minn);
 68     }
 69     while(!_min.empty()) {
 70         cout << _min.front() << " " ;
 71         _min.pop();
 72     }
 73     cout << endl;
 74 }
 75 
 76 void findmax() {
 77     int maxid = 1,o,maxx = -0x7f7f7f;
 78     for(int i = 1;i <= k; i++) {
 79         if(l.empty()) 
 80             l.push_back(i);
 81         o = num[i];
 82         if(o >= maxx) {
 83             maxx = o;
 84             maxid = i;
 85             while(!l.empty()) {
 86                 o = l.front();
 87                 if(num[o] <= maxx) 
 88                     l.pop_front();
 89                 else break;
 90             }
 91             l.push_front(maxid);
 92         }
 93         else {
 94             while(!l.empty()) {
 95                 o = l.back();
 96                 if(num[o] <= num[i]) 
 97                     l.pop_back();
 98                 else break;
 99             }
100             l.push_back(i);
101         }
102     }
103     _max.push(maxx);
104     for(int i = k + 1;i <= n; i++) {
105         if(maxid <= i - k) {
106             l.pop_front();
107             maxid = l.front();
108             maxx = num[maxid];
109         }
110         if(l.empty()) l.push_back(i);
111         o = num[i];
112         if(o >= maxx) {
113             maxx = o;
114             maxid = i;
115             while(!l.empty()) {
116                 o = l.front();
117                 if(num[o] <= maxx)
118                     l.pop_front();
119                 else break;
120             }
121             l.push_front(maxid);
122         }
123         else {
124             while(!l.empty()) {
125                 o = l.back();
126                 if(num[o] <= num[i]) 
127                     l.pop_back();
128                 else break;
129             }
130             l.push_back(i);
131         }
132         _max.push(maxx);
133     }
134     while(!_max.empty()) {
135         cout << _max.front() << " ";
136         _max.pop();
137     }
138 }
139 
140 bool tepan() {
141     if(k == 1) {
142         for(int i = 1;i <= n; i++)
143             cout << num[i] << " ";
144         cout << endl;
145         for(int i = 1;i <= n; i++)
146             cout << num[i] << " ";
147         return true;
148     }
149     else return false;
150 }
151 
152 int main() {
153     scanf("%d%d",&n,&k);
154     for(int i = 1;i <= n; i++) 
155         scanf("%d",&num[i]);
156     if(tepan()) return 0;
157     findmin();
158     while(!l.empty()) l.pop_back();
159     findmax();
160     return 0;
161 }
原文地址:https://www.cnblogs.com/lipeiyi520/p/11237335.html