csdn同步
原題鏈結
簡要題意:
給定 \(n\) 個數 \(\\) 和乙個 \(m\),輸出所有 \(1 \leq i \leq n\) 的 \(\min_^ a_i\).
\(n,m \leq 2 \times 10^6\).
顯然這就是對每個數求出其前 \(m\) 個數的最小值。
樸素令 \(f_i = \min_^ a_i\),\(\mathcal(n^2)\) 炸的飛起。
當然你用線段樹,樹狀陣列,\(\text\) 來維護區間最小都是 \(\mathcal(n \log n)\) 的,不夠優,常數還不一定能過。
我們考慮如何從 \([l,r] \rightarrow [l+1,r+1]\) 即可。
用乙個佇列 \(q\),維護當前可能會影響答案的編號。
什麼叫做可能會影響答案?
比方說當前求的是編號 \(i\) 的答案,那麼顯然,編號 \(u就應該出隊,因為所以包括 \(i\) 在內之後的節點都不可能用到編號 \(u\) 來作為決策了。
其次,如果存在 \(u\) 使得 \(u < i , a_u > a_i\),這時候你會發現,\(i\) 節點的價值比 \(u\) 更高。因為,\(i\) 節點及以後的點用 \(i\) 的次數比用 \(u\) 的次數多,而 \(i\) 的決策又始終比 \(u\) 優,那麼 \(u\) 就可以出隊了。
我們把當前區間的最小值編號始終放在第一位,以便取出。
時間複雜度: \(\mathcal(n)\).(每個點入隊一次,出隊一次)
實際得分:\(100pts\).
#pragma gcc optimize(2)
#includeusing namespace std;
const int n=2e6+1;
inline int read()
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;
int main()
return 0;
}
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 位中的最小元素。先說一句話 單調佇列中,隊首儲存的是最優解,其實是次解,以此類推。所以我們可以構造乙個上公升的單調佇列,隊首弄出來的就是答案。元素的加入不用說,就是那樣子。重點是這裡多了元素的刪除。因為視窗的長度有限,你需要把當前視窗沒有覆蓋...