• BZOJ 3039:玉蟾宫 单调栈/悬线法


    悬线法,刚学的

     转移方程

    if(满足^&%$!@#^%){
        right[i][j]=min(right[i][j],right[i-1][j]);
        left[i][j]=max(left[i][j],left[i-1][j]);
        up[i][j]=up[i-1][j]+1;
    }
    int a=R[i][j]−L[i][j]+1;
    int b=min(a,up[i][j]);
    若要求矩形
    ans=max(ans,a*up[i][j]);
    若要求正方形
    ans=amx(ans,b*b);
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3+ 5;
    int n, m;
    int a[maxn][maxn];
    /*
        up:up[i][j] 用于表示以(i,j)为低端的悬线的长度
        l: l[i][j] 用于表示点(i,j)左端最近的‘R'的纵坐标
        r: r[i][j] 用于表示点(i,j)右端最近的‘R'的纵坐标
        up记录上下最远的距离
        l,r记录点(i,j)左右能到达的最远的距离
    */
    int up[maxn][maxn], l[maxn][maxn], r[maxn][maxn]; 
    int Getchar()
    {
        char ch= getchar();
        while (ch != 'F'&&ch != 'R') ch = getchar();
        return  ch == 'F';
    }
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                a[i][j] = Getchar();
                up[i][j] = 1;
                l[i][j] = r[i][j] = j;
            }
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 2; j <= m; j++)
            {
                if (a[i][j] == 1 && a[i][j - 1] == 1)
                    l[i][j] = l[i][j - 1];
            }
            for (int j = m - 1; j > 0; j--)
            {
                if (a[i][j] == 1 && a[i][j + 1] == 1)
                    r[i][j] = r[i][j + 1];
            }
        }
    
        int max_val = -1;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (i>1&&a[i][j] == 1 && a[i - 1][j] == 1)
                {
                    up[i][j] += up[i - 1][j];
                    l[i][j] = max(l[i - 1][j], l[i][j]);
                    r[i][j] = min(r[i - 1][j], r[i][j]);
                }
                max_val = max(max_val, up[i][j] * (r[i][j] - l[i][j] + 1));
            }
        }
        cout << 3*max_val;
        return 0;
    }
    悬线法

     
    单调栈

    首先处理a[i][j],表示点i,j向上拓展的最大高度,然后对于每一行,就可以就按照书上的最大矩形面积处理,仔细想想,有了a数组以后,1-n行每一行的情况是不是和最大矩形面积那题类似

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3 + 5;
    int n, m, ans = -1;
    /*
        a[i][j]  点(i,j)向上拓展的最大长度
    */
    int a[maxn][maxn], s[maxn], w[maxn];
    int Getchar()
    {
        char ch = getchar();
        while (ch != 'F'&&ch != 'R') ch = getchar();
        return  ch == 'F';
    }
    void solve(int x)
    {
        //memset(s, 0, sizeof(s));
        //memset(w, 0, sizeof(w));
        int tot = 0;
        a[x][m + 1] = 0; //小技巧 保证最后栈是空的
        for (int i = 1; i <= m + 1; i++)
        {
            if (a[x][i] >= s[tot])
            {
                s[++tot] = a[x][i];
                w[tot] = 1;
            }
            else{
                int width = 0;
                while (tot&&s[tot] > a[x][i])
                {
                    width += w[tot];
                    ans = max(ans, width*s[tot]);
                    tot--;
                }
                s[++tot] = a[x][i];
                w[tot] = width + 1;
            }
        }
    }
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (Getchar()) a[i][j] = a[i - 1][j] + 1;
            }
        }
        for (int i = 1; i <= n; i++) 
            solve(i); //这里枚举每一行进行处理
        cout << 3 * ans;
        return 0;
    }
    ```
    单调栈

    再给出一个O(nm2)的做法,这个超时了

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e3+ 5;
    int n, m;
    int a[maxn][maxn];
    int Getchar()
    {
        char ch= getchar();
        while (ch != 'F'&&ch != 'R') ch = getchar();
        return  ch == 'F';
    }
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                a[i][j] = Getchar();
                a[i][j] += a[i][j - 1];  //列上求和
            }
        }
    
        int ans = -1;
        for (int i = 1; i <=m; i++)//枚举列
        {
            for (int j = i; j <= m; j++)//枚举列
            {
                int sum = 0;
                for (int k = 1; k <= n; k++) //枚举行
                {
                    if (a[k][j] - a[k][i - 1] == j - i + 1) sum += j - i + 1; //满足第k行i-j列全为‘F' 
                    else sum = 0;
                    ans = max(ans, sum); //更新答案
                }
            }
        }
        cout << 3*ans;
        return 0;
    }
    O(nm^2)
  • 相关阅读:
    asp.net IIS session丢失 session Key丢失
    本地时间和GMT(UTC)时间的转换(C#)
    <img/>标签onerror事件在IE下的bug和解决方法
    ASP.NET 页面传值方法
    asp.net中URL参数加密解密过程
    Windows 7 MVC2.0部署到IIS7【原创】
    WHENCREATERECORD的三大定律一大推论
    OAF页面查找数据源
    查询用户客户化的文件配置
    EBS AP、AR所有含CCID的业务表
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10362102.html
Copyright © 2020-2023  润新知