• Luogu1169BZOJ1057[ZJOI2007]棋盘制作


    一、悬线法

    原作者博客 https://rpdreamer.blog.luogu.org/p1169

    #include <bits/stdc++.h>
    using namespace std;
    namespace fdata
    {
    inline char nextchar()
    {
        static const int BS = 1 << 21;
        static char buf[BS], *st, *ed;
        if (st == ed)
            ed = buf + fread(st = buf, 1, BS, stdin);
        return st == ed ? -1 : *st++;
    }
    inline int poread()
    {
        int ret = 0;
        char ch;
        while (!isdigit(ch = nextchar()))
            ;
    
        do
            ret = ret * 10 + ch - '0';
        while (isdigit(ch = nextchar()));
        return ret;
    }
    } // namespace fdata
    using fdata::poread;
    const int MAXN = 2005;
    int res[MAXN][MAXN], left_[MAXN][MAXN], right_[MAXN][MAXN], up_[MAXN][MAXN];
    int n, m, ans1, ans2;
    int main()
    {
    #ifdef lky233
        system("color FD");
        freopen("testdata.in", "r", stdin);
        freopen("testdata.out", "w", stdout);
    #endif
        n = poread();
        m = poread();
        for (register int i = 1; i <= n; ++i)
        {
            for (register int j = 1; j <= m; ++j)
            {
                res[i][j] = poread();
                left_[i][j] = right_[i][j] = j;
                up_[i][j] = 1;
            }
        }
        for (register int i = 1; i <= n; ++i)
            for (register int j = 2; j <= m; ++j)
            {
                if (res[i][j] != res[i][j - 1])
                    left_[i][j] = left_[i][j - 1];
            }
        for (register int i = 1; i <= n; ++i)
            for (register int j = m - 1; j > 0; --j)
                if (res[i][j] != res[i][j + 1])
                    right_[i][j] = right_[i][j + 1];
        for (register int i = 1; i <= n; ++i)
            for (register int j = 1; j <= m; ++j)
            {
                if (i > 1 && res[i][j] != res[i - 1][j])
                {
                    left_[i][j] = max(left_[i][j], left_[i - 1][j]);
                    right_[i][j] = min(right_[i][j], right_[i - 1][j]);
                    up_[i][j] = up_[i - 1][j] + 1;
                }
                int a = right_[i][j] - left_[i][j] + 1;
                int b = min(a, up_[i][j]);
                ans1 = max(ans1, b * b);
                ans2 = max(ans2, a * up_[i][j]);
            }
        printf("%d
    %d", ans1, ans2);
    }

    思路:预处理左右边界然后计算长度。

    二、单调栈

    #include <bits/stdc++.h>
    using namespace std;
    namespace fdata
    {
    inline char nextchar()
    {
        static const int BS = 1 << 21;
        static char buf[BS], *st, *ed;
        if (st == ed)
            ed = buf + fread(st = buf, 1, BS, stdin);
        return st == ed ? -1 : *st++;
    }
    inline int poread()
    {
        int ret = 0;
        char ch;
        while (!isdigit(ch = nextchar()))
            ;
    
        do
            ret = ret * 10 + ch - '0';
        while (isdigit(ch = nextchar()));
        return ret;
    }
    } // namespace fdata
    using fdata::poread;
    const int MAXN = 2005;
    int n, m, top, cur, ans1, ans2;
    int stack[MAXN], map[MAXN][MAXN], h[MAXN];
    int main()
    {
    #ifdef lky233
        system("color FD");
        freopen("testdata.in", "r", stdin);
        freopen("testdata.out", "w", stdout);
    #endif
        n = poread();
        m = poread();
        for (register int i = 1; i <= n; ++i)
            for (register int j = 1; j <= m; ++j)
                ::map[i][j] = poread();
        for (register int j = 1; j <= n; ++j)
        {
            for (register int i = 1; i <= m; ++i)
                if (j > 1 && ::map[j][i] != ::map[j - 1][i])
                    ++h[i];
                else
                    h[i] = 1;
            cur = 1;
            while (cur <= m)
            {
                ::stack[0] = cur - 1;
                ::stack[top = 1] = cur++;
                while (cur <= m && ::map[j][cur] != ::map[j][cur - 1])
                {
    
                    while (top && h[::stack[top]] > h[cur])
                    {
                        int x = h[::stack[top]];
                        int y = cur - ::stack[top - 1] - 1;
                        int z = min(x, y);
                        ans1 = max(ans1, z * z), ans2 = max(ans2, x * y), --top;
                    }
                    ::stack[++top] = cur++;
                }
                while (top)
                {
                    int x = h[::stack[top]];
                    int y = cur - ::stack[top - 1] - 1;
                    int z = min(x, y);
                    ans1 = max(ans1, z * z);
                    ans2 = max(ans2, x * y);
                    --top;
                }
            }
        }
        printf("%d
    %d
    ", ans1, ans2);
        return 0;
    }
  • 相关阅读:
    c#以文件流的形式输出xml(可以解决内存溢出)-XmlTextWriter
    c# 大数据量比较时-方案
    c# 大数据量比较时-方案
    sql中插入多条记录-微软批处理
    sql中插入多条记录-微软批处理
    c#上传图片
    c#上传图片
    sql 数据库优化
    mysql处理旧数据-使用模板以及临时表,不建议直接使用本表!!
    margin-bottom无效问题以及div里内容动态居中样式!
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11263334.html
Copyright © 2020-2023  润新知