ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall

本文介绍了一种算法,用于计算一个给定n*m的矩形中不含k个预定义黑点的所有子矩形的数量。通过枚举子矩形的下边界和右边界,并利用记录每列最低黑点位置的数组来快速计算每个可能子矩形的上边界。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解

题目大意 给你一个n*m的矩形 有k个黑点 问这个矩形 不包含黑点的子矩形有多少个

f[i]表示当前枚举状态下 i列的最低黑点位置
暴力枚举子矩形下边界 右边界 利用f数组不断取min则为子矩形的上边界 从右向左扫描
子矩形个数等于枚举子矩形(确定上右左边界的情况下)个数为下边界-f[左边界]

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 10;
int g[MAXN][120], f[120];

int main()
{
#ifdef LOCAL
    freopen("C:/input.txt", "r", stdin);
#endif
    int T;
    cin >> T;
    for (int ti = 1; ti <= T; ti++)
    {
        memset(g, 0, sizeof(g));
        memset(f, 0, sizeof(f));
        int n, m, k;
        cin >> n >> m >> k;
        for (int i = 0; i < k; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            g[x][y] = 1;
        }
        ll ans = 0;
        for (int i = 1; i <= n; i++) //矩形下边界
        {
            for (int j = 1; j <= m; j++) //只更新当前行 下面的黑点不会对当前行造成影响
                if (g[i][j])
                    f[j] = i; //第i列最低的黑点位置
            for (int r = 1; r <= m; r++) //矩形右边界
            {
                int mi = INF; //矩形上边界+1
                for (int l = r; l >= 1; l--)
                {
                    mi = min(mi, i - f[l]); //从右向左扫 子矩形个数为下边界-最低黑点+1
                    ans += mi;
                }
            }
        }
        printf("Case #%d: %lld\n", ti, ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值