1. 程式人生 > >洛谷 P1440 求m區間內的最小值(單調隊列)

洛谷 P1440 求m區間內的最小值(單調隊列)

ac代碼 ati space value .org 意思 pro htm src

題目鏈接

https://www.luogu.org/problemnew/show/P1440


顯然是一道單調隊列題目……


解題思路

對於單調隊列不明白的請看這一篇博客:https://www.cnblogs.com/yinyuqin/p/10492882.html

這道題和模板唯一的不同點就是從0開始,一直輸出n次。什麽意思呢?

  • 普通單調隊列:單調隊列中數據到達m個再輸出
  • 本題:從沒有數據時就開始輸出。

詳細點說,就是輸出0到0,0到1,0到2……一直到0到m-1,接著是1到m,2到m+1,3到m+2……一直到n-m到n-1的最小值。

具體可以研究一下樣例,很容易就可以理解。

所以我們只需要在輸出上做一點修改。

如果隊列為空,說明這是第一個元素,就輸出0到0之間的最小值,顯然是0。

否則就每次在讀入一個數之前,就輸出單調隊列裏面的最小值。

而且我們發現,最後讀入的數其實是沒有用的!!坑啊

艱辛的做題過程

首先是TLE:

技術分享圖片

找了好長時間的bug,沒想到竟然是cin cout 搞的!!盤他

十年oi一場空,cin、cout見祖宗。

然後是莫名RE:

技術分享圖片

原來當m==1時,少判斷了一個q.empty()會爆掉。。。

無語。。。。。

AC代碼

 1 #include<iostream>
 2
#include<deque> 3 #include<cstdio> 4 using namespace std; 5 int n,m; 6 struct num{ //儲存每一個點的信息 7 int cnt,value; //cnt是編號 value是值 8 num(int a,int b):cnt(a),value(b){}//構造函數 9 }; 10 deque<num> q; //定義一個雙端隊列,註意頭文件
11 void makeq(int i,int in){ //見另一篇博客 12 if(q.empty()) q.push_back(num(i,in)); 13 else{ 14 num f=q.front(); 15 if(i>=f.cnt+m) q.pop_front(); 16 if(!q.empty()){ //註意判斷隊列是否為空 17 num b=q.back(); 18 while(in<=b.value){ 19 q.pop_back(); 20 if(q.empty()) break;//註意再次判斷隊列是否為空 21 b=q.back(); 22 } 23 } 24 q.push_back(num(i,in)); 25 } 26 } 27 int main(){ 28 cin>>n>>m; 29 for(int i=1;i<=n;i++){ 30 if(q.empty()) printf("0\n");//第一個輸出0 31 else printf("%d\n",q.front().value);//後來每次輸出單調隊列的最小值 32 int in; 33 scanf("%d",&in); //註意用scanf 34 makeq(i,in); //讓這個點入隊 35 } 36 return 0; 37 }

洛谷 P1440 求m區間內的最小值(單調隊列)