zoukankan      html  css  js  c++  java
  • HZNUACM寒假集训Day10小结 单调栈单调队列

     数据结构往往可以在不改变主算法的前提下题高运行效率,具体做法可能千差万别,但思路却是有规律可循

     经典问题:滑动窗口  单调队列O(n)

     POJ 2823 

     我开始写的: TLE 说明STL的库还是有点慢

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    
    struct Deq {
        int idx;
        int w;
    };
    
    deque<Deq> q;
    deque<Deq> qq;
    int Max[1000005];
    
    int main() {
        int n, k;
        int x;
        int cnt = 0;
        scanf("%d%d", &n, &k);
        for (int i = 0; i < n; i++) {
            if (i < k) {
                scanf("%d", &x);
                Deq qqq;
                qqq.idx = i;
                qqq.w = x;
                if (q.empty()) q.push_back(qqq);
                if (qq.empty()) qq.push_back(qqq);
                else {
                    while (!q.empty() && q.back().w < x) q.pop_back();
                    q.push_back(qqq);
                    while (!qq.empty() && qq.back().w > x) qq.pop_back();
                    qq.push_back(qqq);
                }
                if (i == k - 1) {
                    printf("%d", qq.front().w);
                    Max[cnt++] = q.front().w;
                }
            }
            else {
                scanf("%d", &x);
                Deq qqq;
                qqq.idx = i;
                qqq.w = x;
                if (q.empty()) q.push_back(qqq);
                if (qq.empty()) qq.push_back(qqq);
                else {
                    while (!q.empty() && q.back().w < x) q.pop_back();
                    q.push_back(qqq);
                    while (!qq.empty() && qq.back().w > x) qq.pop_back();
                    qq.push_back(qqq);
                }
                while (q.front().idx < i + 1 - k) q.pop_front();
                while (qq.front().idx < i + 1 - k) qq.pop_front();
                printf(" %d", qq.front().w);
                Max[cnt++] = q.front().w;
            }
        }
        printf("\n");
        for (int i = 0; i < cnt; i++) {
            i == 0 ? printf("%d", Max[i]) : printf(" %d", Max[i]);
        }
        return 0;
    }
    View Code

     洛谷题解:

      直接用下标存进队列 手写双端队列

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    const int maxn = 1000005;
    int n, m;
    int q1[maxn], q2[maxn];
    int a[maxn];
    
    void Min_que() {
        int h = 1;     //head
        int t = 0;     //tail
        for (int i = 1; i <= n; i++) {
            while (h <= t && q1[h] + m <= i)    h++;
            while (h <= t && a[i] < a[q1[t]]) t--;
            q1[++t] = i;
            if (i >= m) printf("%d ", a[q1[h]]);
        }
        printf("\n");
    }
    
    void Max_que() {
        int h = 1;
        int t = 0;
        for (int i = 1; i <= n; i++) {
            while (h <= t && q2[h] + m <= i) h++;
            while (h <= t && a[i] > a[q2[t]]) t--;
            q2[++t] = i;
            if (i >= m) printf("%d ", a[q2[h]]);
        }
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        Min_que();
        Max_que();
        return 0;
    }
    View Code

      单调栈:

      

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    
    struct S {
        int idx;
        int w;
    };
    stack<S> s;
    int a[3000005];
    vector<int> f;
    
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);
        for (int i = n - 1; i >= 0; i--) {
            if (i == n - 1) {
                f.push_back(0);
                s.push({ i,a[i] });
            }
            else {
                if (s.empty()) {
                    f.push_back(0);
                    s.push({ i,a[i] });
                }
                else {
                    while (!s.empty()&&s.top().w <= a[i]) s.pop();
                    if (!s.empty()) f.push_back(s.top().idx+1);
                    else f.push_back(0);
                    s.push({ i,a[i] });
                }
            }
        }
        for (auto it = f.rbegin(); it != f.rend(); it++) {
            if (it == f.rbegin()) printf("%d", *it);
            else printf(" %d", *it);
        }
        return 0;
    }
    View Code

       HDU 1506

      题目题意:题目给了n个矩形的高度,问最大连续矩形的公共面积(底乘以这段连续矩形中最短的高度),每个矩形的底是1

      感觉有点像贪心,想了很久没想出单调栈的做法 事实上需要维护一个递增的矩形,每次出栈维护最大值

      

       

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    const int maxn = 100005;
    int a[maxn];  
    int s[maxn], w[maxn];
    
    ll ans;
    
    int main() {
        int n;
        while (scanf("%d", &n) != EOF) {
            if (!n) break;
            int p = 0;
            ans = 0;
            for (int i = 1; i <=n; i++) scanf("%d", &a[i]);
            a[n+1] = 0;                                      //注意设置a[0]=0,a[n+1]=0,因为最后一个也可能出栈
            for (int i = 1; i <= n+1; i++) {
                if (a[i] > s[p]) s[++p] = a[i], w[p] = 1;  //维护单调递增的栈
                else {
                    int wid = 0;
                    while (s[p] > a[i]) {
                        wid += w[p];
                        ans = max(ans, (ll)wid * s[p]);     //core
                        p--;
                    }
                    s[++p] = a[i];
                    w[p] = wid + 1;
                }
            }
            printf("%lld\n", ans);
        }
        return 0;
    }
    View Code

      

      POJ 3494 求一个0-1矩阵中全为1的最大子矩阵。

      

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    const int maxn = 2010;
    int mp[maxn][maxn];
    int h[maxn][maxn];
    int L[maxn], R[maxn], st[maxn];
    
    int main() {
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    scanf("%d", &mp[i][j]);
                }
            }
            for (int i = 0; i < m; i++) {
                int high = 0;
                for (int j = n - 1; j >= 0; j--) {
                    if (mp[j][i])  high++;
                    else high = 0;
                    h[j][i] = high;
                }
            }
            int ans = 0;
            for (int i = 0; i < n; i++) {
                int pos = 0;
                for (int j = 0; j < m; j++) {
                    while (pos > 0 && h[i][st[pos - 1]] >= h[i][j]) pos--;
                    L[j] = pos == 0 ? 0 : st[pos - 1] + 1;
                    st[pos++] = j;
                }
                pos = 0;
                for (int j = m - 1; j >= 0; j--) {
                    while (pos > 0 && h[i][st[pos - 1]] >= h[i][j]) pos--;
                    R[j] = pos == 0 ? m - 1 : st[pos - 1] - 1;
                    st[pos++] = j;
                }
                for (int j = 0; j < m; j++) {
                    ans = max(ans, h[i][j] * (R[j] - L[j] + 1));
                }
            }
            printf("%d\n", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    c# XML和实体类之间相互转换(序列化和反序列化)
    反序列化-通过创建Class对象及属性
    .net C#中页面之间传值传参的六种方法
    C#对XML、JSON等格式的解析
    c#大圣之路笔记——c# DataGrid checkbox 操作
    python(十五)
    python(十四)
    python(十三)
    python(十二)
    python(十一)
  • 原文地址:https://www.cnblogs.com/hznumqf/p/12287009.html
Copyright © 2011-2022 走看看