WA on 3 求助

P1886 滑动窗口 /【模板】单调队列

实际上输出的结果也是一样的
by SICKO @ 2023-12-04 17:44:42


已解决,$n==1$ 时并不是能一次性弹出所有队列中的不合法队头(数列第一个数会被插入两次)。 ```c++ #include<iostream> #include<vector> #include<algorithm> #include<deque> using namespace std; const int N = 1e6+6; deque<int> my_queue; int num[N]; vector<int> min_ans; vector<int> max_ans; int main() { int n, m; cin>>n>>m; for(int i=1; i<=n; i++) { cin>>num[i]; } // if(m == 1) // { // for(int i=1; i<=n; i++) cout<<num[i]<<" "; // cout<<"\n"; // for(int i=1; i<=n; i++) cout<<num[i]<<" "; // return 0; // } //-------------------------------------------------------------------------------------------------------------------- // 滑动窗口,处理最大值问题,则维护一个单调递减的队列 // 预处理第一步,队列里面得有东西 my_queue.push_back(1); // 预处理第二步,留下有可能成为最大值的值的地址 for(int i=2; i<m; i++) { // 如果这个值比队尾的值要小或相等,那么队尾的值有可能成为之后区间的最大值,这个值也是,所以我们入队 if(num[i] <= num[my_queue.back()]) { my_queue.push_back(i); } // 如果这个值比队尾的值要大,那么队尾的值一定不可能成为之后区间的最大值了,我们就后端出列直到空或者符合小于等于 else while(true) { my_queue.pop_back(); if(my_queue.empty()) { my_queue.push_back(i); break; } if(num[i] <= num[my_queue.back()]) { my_queue.push_back(i); break; } } } // 主处理函数 for(int i=m; i<=n; i++) { // 再重复一遍之前的处理 // 如果这个值比队尾的值要小或相等,那么队尾的值有可能成为之后区间的最大值,这个值也是,所以我们入队 if(num[i] <= num[my_queue.back()]) { my_queue.push_back(i); } // 如果这个值比队尾的值要大,那么队尾的值一定不可能成为之后区间的最大值了,我们就后端出列直到空或者符合小于等于 else while(true) { my_queue.pop_back(); if(my_queue.empty()) { my_queue.push_back(i); break; } if(num[i] <= num[my_queue.back()]) { my_queue.push_back(i); break; } } // 最后别忘了判断队头是否合法。怎么判断,如果这个队头加上 m 的值小于等于当前位置,那么说明队头不在窗口内 while(my_queue.front()+m<=i) my_queue.pop_front(); // 到了主处理函数处,我们就可以判断最大最小值了,按照之前的处理,最大值一定会出现在对头 max_ans.push_back(num[my_queue.front()]); } //--------------------------------------------------------------------------------------------------------------------- // 接下来就是处理最小值问题了,最小值问题,我们就得维护单调递增的队列 // 别忘了清空队列 my_queue.clear(); // 预处理第一步,队列里面得有东西 my_queue.push_back(1); // 预处理第二步,留下有可能成为最小值的值 for(int i=2; i<m; i++) { // 如果这个值比队尾的要大或者相等,那么说明这两值有可能成为之后的最小值,我们加到队列里面 if(num[i] >= num[my_queue.back()]) { my_queue.push_back(i); } else while(true) { // 否则队尾一定不可能成为之后区间的最小值,我们不断弹出队尾直到找到目标 my_queue.pop_back(); if(my_queue.empty()) { my_queue.push_back(i); break; } if(num[i] >= num[my_queue.back()]) { my_queue.push_back(i); break; } } } // 主处理 for(int i=m; i<=n; i++) { // 照搬之前操作 // 如果这个值比队尾的要大或者相等,那么说明这两值有可能成为之后的最小值,我们加到队列里面 if(num[i] >= num[my_queue.back()]) { my_queue.push_back(i); } else while(true) { // 否则队尾一定不可能成为之后区间的最小值,我们不断弹出队尾直到找到目标 my_queue.pop_back(); if(my_queue.empty()) { my_queue.push_back(i); break; } if(num[i] >= num[my_queue.back()]) { my_queue.push_back(i); break; } } // 别忘了判断队头是否合法。怎么判断,如果这个队头加上 m 的值小于等于当前位置,那么说明队头不在窗口内 while(my_queue.front()+m<=i) my_queue.pop_front(); // 到了主处理函数处,我们就可以判断最大最小值了,按照之前的处理,最小值一定会出现在对头 min_ans.push_back(num[my_queue.front()]); } // 输出答案 for(int i:min_ans) { cout<<i<<" "; } cout<<"\n"; for(int i:max_ans) { cout<<i<<" "; } return 0; } ``` 把 `if` 判断方法改为 `while` 即可。
by SICKO @ 2023-12-05 21:23:02


|