zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    省选模板_简单数学
    省选模板大杂烩
    省选_简单算法
    省选_简单图论
    省选_简单数据结构
    BZOJ4545: DQS的trie 广义后缀自动机 + LCT
    BZOJ 4229: 选择 LCT + 独创方法 + 边双
    luoguP2742 【模板】二维凸包 / [USACO5.1]圈奶牛 二维凸包
    python面向过程编程小程序 -ATM(里面用了终端打印)
    从7点到9点写的小程序(用了模块导入,python终端颜色显示,用了点局部和全局可变和不可变作用域,模块全是自定义)
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11263334.html
Copyright © 2011-2022 走看看