【單調隊列】POJ2823-Sliding Window


單調隊列經典題之一。

【思路】

設置兩個單調隊列分別記錄最大值和最小值。對於每一個新讀入的數字,進行兩次操作(對於求最大值和最小值中的某一個而言),一是若隊首不在滑窗范圍內則刪去;二是刪去隊末比當前值小(或大)的值,並將當前值插入對尾。每一次的最小(大)值就是當前單調隊列的隊首。

【錯誤點】

一定要寫while (scanf("%d%d",&n,&k)!=EOF),否則會WA。

我一開始的做法是這樣的:先把第一個數插入隊尾,再從第二個數開始進行后續操作。這樣的問題在於如果滑窗大小為1,則第一個數無法被輸出就出隊,導致WA。故一定要先設置一個空隊列,再逐一插入。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int MAXN=1000000+10;
 5 int n,k,maxh,minh,maxt,mint; 
 6 int maxq[MAXN],minq[MAXN],num[MAXN];
 7 int maxans[MAXN],minans[MAXN];
 8 
 9 int main()
10 {
11     while (scanf("%d%d",&n,&k)!=EOF)
12     {
13         int maxhead=0,minhead=0,maxtail=0,mintail=0;
14         for (int i=0;i<n;i++)
15         {
16             /*刪除下標超出范圍的隊首元素*/ 
17             if (maxhead<maxtail && maxq[maxhead]<=i-k) maxhead++;
18             if (minhead<mintail && minq[minhead]<=i-k) minhead++;
19             
20             
21             /*刪除隊尾元素*/ 
22             scanf("%d",&num[i]);
23             while (maxhead<maxtail && num[maxq[maxtail-1]]<=num[i]) maxtail--;maxtail++;
24             maxq[maxtail-1]=i;
25             while (minhead<mintail && num[minq[mintail-1]]>=num[i]) mintail--;mintail++;
26             minq[mintail-1]=i;
27             maxans[i]=num[maxq[maxhead]];
28             minans[i]=num[minq[minhead]];            
29         }
30         for (int i=k-1;i<n;i++) cout<<minans[i]<<' ';cout<<endl;
31         for (int i=k-1;i<n;i++) cout<<maxans[i]<<' ';cout<<endl;
32     }
33     return 0;
34 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM