首页 > 代码库 > Codeforces Round #248 (Div. 1)——Nanami's Digital Board

Codeforces Round #248 (Div. 1)——Nanami's Digital Board

题目连接

  • 题意:
    给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值
    (1?≤?n,?m,?q?≤?1000)
  • 分析:
    考虑以(x,y)为下边界的情况,h=(x,y)上边最多的连续1的个数。那么递减的枚举,对于当前hx,只需要看两侧能到达的最远距离,使得h(x,ty)不大于h即可。之后的枚举得到的两侧距离大于等于之前的,所以继续之前的两侧距离继续枚举即可。
const int maxn = 1100;

int n, m, q;
int ipt[maxn][maxn];
int up[maxn][maxn], dwn[maxn][maxn], lft[maxn][maxn], rht[maxn][maxn];
int len[maxn];
void updaterow(int r)
{
    FE(j, 1, m)
        lft[r][j] = (ipt[r][j] == 1 ? lft[r][j - 1] + 1 : 0);
    FED(j, m, 1)
        rht[r][j] = (ipt[r][j] == 1 ? rht[r][j + 1] + 1 : 0);
}
void updatecol(int c)
{
    FE(i, 1, n)
        up[i][c] = (ipt[i][c] == 1 ? up[i - 1][c] + 1 : 0);
    FED(i, n, 1)
        dwn[i][c] = (ipt[i][c] == 1 ? dwn[i + 1][c] + 1 : 0);
}
int maxarea(int s, int len[], int thes)
{
    int l = s, r = s, ret = 0;
    FED(i, len[s], 1)
    {
        while (l >= 1 && len[l] >= i)
            l--;
        while (r <= thes && len[r] >= i)
            r++;
        ret = max(ret, i * (r - l - 1));
    }
    return ret;
}

int main()
{
    while (~RIII(n, m, q))
    {
        FE(i, 1, n) FE(j, 1, m)
            RI(ipt[i][j]);
        FE(i, 1, n)
            updaterow(i);
        FE(j, 1, m)
            updatecol(j);
        REP(kase, q)
        {
            int op, x, y;
            RIII(op, x, y);
            if (op == 1)
            {
                ipt[x][y] ^= 1;
                updatecol(y);
                updaterow(x);
            }
            else
            {
                int ans = max(maxarea(y, up[x], m), maxarea(y, dwn[x], m));
                FE(i, 1, n)
                    len[i] = lft[i][y];
                ans = max(ans, maxarea(x, len, n));
                FE(i, 1, n)
                    len[i] = rht[i][y];
                ans = max(ans, maxarea(x, len, n));
                WI(ans);
            }
        }
    }
    return 0;
}