P1440 求m區間內的最小值 題解

2021-10-07 19:02:43 字數 2237 閱讀 5539

同步

原題鏈結

簡要題意:

給定 n

nn 個數

\和乙個 m

mm,輸出所有 1≤i

≤n

1 \leq i \leq n

1≤i≤

n 的 min

⁡max⁡(

1,i−

m+1)

ia

i\min_^ a_i

minmax(1

,i−m

+1)i

​ai​.n,

m≤2×

10

6n,m \leq 2 \times 10^6

n,m≤2×

106.

顯然這就是對每個數求出其前 m

mm 個數的最小值

樸素令 fi=

min⁡

max⁡(1

,i−m

+1)i

ai

f_i = \min_^ a_i

fi​=

minmax(1

,i−m

+1)i

​ai​

,o (n

2)

\mathcal(n^2)

o(n2

) 炸的飛起。

當然你用線段樹,樹狀陣列,rmq

\text

rmq 來維護區間最小都是 o(n

log⁡n)

\mathcal(n \log n)

o(nlogn)

的,不夠優,常數還不一定能過。

我們考慮如何從 [l,

r]→[

l+1,

r+1]

[l,r] \rightarrow [l+1,r+1]

[l,r]→

[l+1

,r+1

] 即可。

用乙個佇列 q

qq,維護當前可能會影響答案的編號

什麼叫做可能會影響答案

比方說當前求的是編號 i

ii 的答案,那麼顯然,編號 u

m+1u

um+1 就應該出隊,因為所以包括 i

ii 在內之後的節點都不可能用到編號 u

uu 來作為決策了

其次,如果存在 u

uu 使得 u

au

>ai

u < i , a_u > a_i

uau​>ai

​,這時候你會發現,i

ii 節點的價值比 u

uu 更高。因為,i

ii 節點及以後的點用 i

ii 的次數比用 u

uu 的次數多,而 i

ii 的決策又始終比 u

uu 優,那麼 u

uu 就可以出隊了。

我們把當前區間的最小值編號始終放在第一位,以便取出。

時間複雜度: o(n

)\mathcal(n)

o(n)

.(每個點入隊一次,出隊一次)

實際得分:100pt

s100pts

100pts

.

#pragma gcc optimize(2)

#include

using

namespace std;

const

int n=

2e6+1;

inline

intread()

int x=0;

while

(ch>=

'0'&& ch<=

'9') x=

(x<<3)

+(x<<1)

+ch-

'0',ch=

getchar()

;return x*f;

}inline

void

write

(int x)

if(x<10)

write

(x/10);

putchar

(char

(x%10

+'0'))

;}int n,m,a[n]

,q[n]

;int l=

1,r=0;

intmain()

return0;

}

P1440 求M區間內的最小值

乙個含有 nn 項的數列,求出每一項前的 mm 個數到它這個區間內的最小值。若前面的數不足 mm 項則從第 11 個數開始,若前面沒有數則輸出 00。第一行兩個整數,分別表示 nn,mm。第二行,nn 個正整數,為所給定的數列 a ia i nn 行,每行乙個整數,第 ii 個數為序列中 a ia ...

P1440 求m區間內的最小值

乙個含有n項的數列 n 2000000 求出每一項前的m個數到它這個區間內的最小值。若前面的數不足m項則從第1個數開始,若前面沒有數則輸出0。輸入格式 第一行兩個數n,m。第二行,n個正整數,為所給定的數列。輸出格式 n行,第i行的乙個數ai,為所求序列中第i個數前m個數的最小值。輸入樣例1 627...

P1440 求m區間內的最小值

這道題就是經典的滑動視窗問題了。要求你求某乙個數的前 m 位中的最小元素。先說一句話 單調佇列中,隊首儲存的是最優解,其實是次解,以此類推。所以我們可以構造乙個上公升的單調佇列,隊首弄出來的就是答案。元素的加入不用說,就是那樣子。重點是這裡多了元素的刪除。因為視窗的長度有限,你需要把當前視窗沒有覆蓋...