洛谷P1886 滑動視窗 /【模板】單調佇列 /Poj 2823 Sliding Windows
阿新 • • 發佈:2021-11-10
【題目】
【審題】
略。
【分析】
1.問:暴力怎麼寫?
答:列舉區間起點,直接模擬。時間複雜度O(nk).
2.問:為什麼用單調佇列更優?
答:(1)單調佇列中的元素或相關資料具有單調性,可用於求最值。
(2)單調佇列中的元素下標一定遞增,符合視窗滑動的特點。
3.問:還可以用什麼來實現?
答:線段樹、st表(都為nlogn),但資料範圍1e6,必定會卡。
【做題時遇到的問題】
如圖,第一種寫法沒有先判重就呼叫了q.back(),導致RE。
在csp-s 2021 的時候想到過這個問題,但是沒有今天這麼透徹。當時的做法是如果優先佇列為空,則單獨設一個值為0的變數來比較。
【程式碼實現】
#include<bits/stdc++.h> using namespace std; deque<int> q; int n,m,a[1000005]; int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ // while(a[i]<a[q.back()]&&!q.empty()){// q.pop_back(); // } while(!q.empty()&&a[i]<a[q.back()]) q.pop_back(); q.push_back(i); if(i>=m) { while(i-q.front()>=m&&!q.empty()) { q.pop_front(); } printf("%d ",a[q.front()]); } } printf("\n"); while(!q.empty()) q.pop_front(); for(int i=1;i<=n;i++){ while(!q.empty()&&a[i]>a[q.back()]) q.pop_back(); q.push_back(i); if(i>=m) { while(i-q.front()>=m&&!q.empty()) { q.pop_front(); } printf("%d ",a[q.front()]); } } return 0; }