1. 程式人生 > 實用技巧 >題解 HDU3306 【Another kind of Fibonacci】

題解 HDU3306 【Another kind of Fibonacci】

滑動視窗

給一個長度為N的陣列,一個長為K的滑動窗體從最左端移至最右端,你只能看到視窗中的K個數,每次窗體向右移動一位你的任務是找出窗體在各個位置時的最大值和最小值。
連結:https://ac.nowcoder.com/acm/problem/50528
來源:牛客網

單調佇列,以單調遞增為例:使用雙端佇列,若堆頭元素不在視窗內則彈出隊頭,若隊尾元素小於當前元素則彈出隊尾,最後將當前元素插入隊尾。隊頭元素就是最大值。

這個題時間空間卡的都很死。

#include <bits/stdc++.h>

using namespace std;

const int INF = 0x3f3f3f3f;

int res[1000010],cnt=0;

struct Num{
public:
    int value;
    int location;
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, k, t;
    cin >> n >> k;
    deque<Num> big(1000010), small(1000010);
    for(int i = 0;i < n; i++){
        cin >> t;
        while(!big.empty() && ((i - big.front().location + 1) > k))big.pop_front();
        while(!big.empty() && big.back().value < t)big.pop_back();
        while(!small.empty() && ((i - small.front().location + 1) > k))small.pop_front();
        while(!small.empty() && small.back().value > t)small.pop_back();
        big.push_back({t, i});
        small.push_back({t, i});
        if(i >= k - 1){
            res[cnt++] = (big.front().value);
            cout << small.front().value;
            if(i != n - 1){
                cout << " ";
            }
        }
    }
    cout << endl;
    for(int i = 0;i < cnt;i++){
        cout << res[i];
        if(i != cnt - 1)cout << " ";
    }
    cout << endl;
}