Luogu P1440 求m區間內的最小值

2022-08-22 11:09:12 字數 1549 閱讀 4980

# 這題可以用rmq(st表)做!

由於本題資料的特殊性,需要查詢的區間的元素個數大部分是一樣的(除了輸出的前$m$行元素個數不足$m$個的情況),我們就可以把st表(**中$a$陣列)進行降維攻擊(霧)!這樣一來使用rmq(st表)就不會mle了!

在時間方面,我們可以拿個變數(**中$power$)儲存$2$的$j$次方,這樣就不需要每一步都進行位運算了,這樣做竟把超時的乙個點卡過去了……

時空問題都解決了,接下來只要和一般的rmq(st表)進行相同的操作就可以了。

但我們似乎忽略了乙個問題……

就是輸出的前$m$行元素個數不足$m$個時,我們要從第乙個元素開始找,元素個數肯定不到$m$個。但最後因降過維,我們只能輸出元素個數為$m$的區間的最小值,這下應該怎麼辦呢?

這時我們可以想到,區間元素個數小於$m$時是在倍增預處理的時候,這時的st表還未定型,在中途過程中會出現我們需要的答案,所以這部分的答案要在我們倍增的過程中輸出。

我們發現,倍增過程中的每一層要輸出的答案個數是不同的:

1. 第乙個輸出肯定為$0$,因為第乙個數前是沒有數的;

2. 如果$m>1$,那麼第二個輸出肯定是第乙個數,因為第二個數前面只有乙個數;

3. 我們手推一下可以發現,在建st表的過程中,編號小於等於$2 \times power$的答案可以直接輸出(當然僅限於編號小於$m$的數,即元素個數不足$m$個);

4. 剩下的數就直接在st表建好後按正常rmq方法輸出最小值就可以啦~

pascal**如下:

uses math;//log2要用math庫qwq

varn,m,i,j,k,l,power:longint;

a:array[0..2000000]of

longint;

begin

readln(n,m);

for i:=1

to n do

read(a[i]);

writeln(

0);//情況1

if m>1

then//情況2

writeln(a[

1]);

k:=trunc(log2(m));

l:=2;//l為當前應輸出第l個答案

power:=1

;for j:=1

to k do//建st表

begin

power:=power*2

;for i:=1

to n-power+1

doa[i]:=min(a[i],a[i+power div

2]);

while (l<=power*2)and(ldo//情況3

begin

writeln(min(a[

1],a[l-power+1

]));

inc(l);

end;

end;

for i:=1

to n-m do//情況4

writeln(min(a[i],a[i+m-power]),'');

end.

luogu P1440 求m區間內的最小值

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

luogu P1440 求m區間內的最小值

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

P1440 求M區間內的最小值

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