描述
有一串整數在排隊……
有N個整數,你有一個可以框住M個連續段整數的木框,現在你想知道,對於這個隊列中任意的連續M個整數,最大和最小的整數是哪個?
例:(M大小的視窗向右滑動)
1 2 3 2 1 M=2
1 2 MAX 2 MIN 1
2 3 MAX 3 MIN 2
3 2 MAX 3 MIN 2
2 1 MAX 2 MIN 1
最後需要輸出的是兩行:
1 2 2 1
2 3 3 2
-
輸入
-
第一行包含一個整數T,表示有T組測試資料;
以下每組測試資料格式:
第一行包含2個整數N,M表示有N個整數在排隊,取連續M個整數。
第二行包含N個整數。
其中N不大於1,000,000,M不大於N。
-
輸出
-
按照題目描述格式輸出結果,第一行為MIN,第二行為MAX。
-
範例輸入
-
1
-
5 2
-
1 2 3 2 1
-
範例輸出
-
1 2 2 1
-
2 3 3 2
-
提示
-
注意資料規模!
明顯簡單的方法無效,資料規模很大,這裡用線段樹來做,也可以來看http://blog.tomtung.com/ 部落格,其中有更好的解法
#include<iostream>#include<queue>#include<vector>using namespace std;const int M = 1000010;int A[M], mi[M], ma[M];struct Cmpa{bool operator ()(const int &a, const int &b){return A[a] < A[b];}};struct Cmpi{bool operator ()(const int &a, const int &b){return A[a] > A[b];}};priority_queue<int, vector<int>, Cmpi> qi;priority_queue<int, vector<int>, Cmpa> qa;int main(){int i, j, k, n, m, t, l;scanf("%d", &t);while(t--) {scanf("%d%d", &n, &m);for(i = 0; i < n; i++) scanf("%d", &A[i]);for(i = 0; i < m-1; i++) {qi.push(i); qa.push(i);}l = 0;for(i = m-1; i < n; i++) {qi.push(i); qa.push(i);while(i - qi.top() >= m) qi.pop();while(i - qa.top() >= m) qa.pop();mi[l] = A[qi.top()];ma[l++] = A[qa.top()];}for(i = 0; i < l-1; i++) printf("%d ", mi[i]);printf("%d\n", mi[i]);for(i = 0; i < l-1; i++) printf("%d ", ma[i]);printf("%d\n", ma[i]);}return 0;}