# 這題可以用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庫qwqvarn,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 ...