長度 n(≤10⁶)數組,窗口大小 k,窗口從左向右滑動。輸出每個窗口的最小值和最大值。
#includeusing namespace std; const int MAXN = 1000005; int n, k, a[MAXN]; int q[MAXN], head, tail; int mn[MAXN], mx[MAXN]; // 最小值隊列:單調遞增 void push_min(int i) { while (head < tail && a[i] <= a[q[tail-1]]) --tail; q[tail++] = i; } // 最大值隊列:單調遞減 void push_max(int i) { while (head < tail && a[i] >= a[q[tail-1]]) --tail; q[tail++] = i; } // 移除超出窗口的元素 void pop(int i) { if (q[head] <= i - k) ++head; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); while (cin >> n >> k) { for (int i = 1; i <= n; ++i) cin >> a[i]; // 求最小值 head = tail = 0; for (int i = 1; i < k; ++i) push_min(i); int mcnt = 0; for (int i = k; i <= n; ++i) { push_min(i); pop(i); mn[mcnt++] = a[q[head]]; } // 求最大值 head = tail = 0; for (int i = 1; i < k; ++i) push_max(i); int xcnt = 0; for (int i = k; i <= n; ++i) { push_max(i); pop(i); mx[xcnt++] = a[q[head]]; } // 輸出 for (int i = 0; i < mcnt; ++i) { if (i) cout << ' '; cout << mn[i]; } cout << '\n'; for (int i = 0; i < xcnt; ++i) { if (i) cout << ' '; cout << mx[i]; } cout << '\n'; } return 0; }
| 操作 | 最小值隊列 | 最大值隊列 |
|---|---|---|
| 單調性 | 遞增(隊首最小) | 遞減(隊首最大) |
| 入隊彈出條件 | a[i] <= a[q[tail-1]] | a[i] >= a[q[tail-1]] |
| 出隊條件 | q[head] <= i - k(下標 ≤ 窗口左邊界) | |
| 窗口形成時刻 | i ≥ k 時輸出隊首值 | |
while(cin>>n>>k) 讀至 EOF