同步
原題鏈結
簡要題意:
給定 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
logn)
\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 位中的最小元素。先說一句話 單調佇列中,隊首儲存的是最優解,其實是次解,以此類推。所以我們可以構造乙個上公升的單調佇列,隊首弄出來的就是答案。元素的加入不用說,就是那樣子。重點是這裡多了元素的刪除。因為視窗的長度有限,你需要把當前視窗沒有覆蓋...