[杂题]AGC015C - Nuske vs Phantom Thnook

22 篇文章 0 订阅
9 篇文章 0 订阅

Description

给定一张网格图。图中的两个黑点右边当且仅当相邻。
求子网格图 (x1,y1,x2,y2) 中联通块的个数。
保证两个点之间不连通或只存在一条简单路径。

Solution

森林的联通块个数=点数-边数。

#include <bits/stdc++.h>
using namespace std;

const int N = 2020;

inline char get(void) {
    static char buf[100000], *S = buf, *T = buf;
    if (S == T) {
        T = (S = buf) + fread(buf, 1, 100000, stdin);
        if (S == T) return EOF;
    }
    return *S++;
}
inline void read(int &x) {
    static char c; x = 0;
    for (c = get(); c < '0' || c > '9'; c = get());
    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
inline void read(char *ch) {
    static char c; int len = 0;
    for (c = get(); c < '0' || c > '1'; c = get());
    for (; c == '0' || c == '1'; c = get()) ch[len++] = c;
}

int n, m, q, x1, x2, y11, y2, E, V;
char ch[N][N];
int num[N][N], edg[N][N];
int pr1[N][N], pr2[N][N];

inline int Edge(int x, int y) {
    return (ch[x][y] == '1' && ch[x][y - 1] == '1') + (ch[x][y] == '1' && ch[x - 1][y] == '1');
}

int main(void) {
    read(n); read(m); read(q);
    for (int i = 1; i <= n; i++) read(ch[i] + 1);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            num[i][j] = num[i - 1][j] + num[i][j - 1] - num[i - 1][j - 1] + (ch[i][j] == '1');
    for (int i = 2; i <= n; i++)
        for (int j = 1; j <= m; j++)
            pr1[i][j] = pr1[i][j - 1] + (ch[i][j] == '1' && ch[i - 1][j] == '1');
    for (int i = 1; i <= n; i++)
        for (int j = 2; j <= m; j++)
            pr2[i][j] = pr2[i - 1][j] + (ch[i][j] == '1' && ch[i][j - 1] == '1');
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            edg[i][j] = edg[i - 1][j] + edg[i][j - 1] - edg[i - 1][j - 1] + Edge(i, j);
    while (q--) {
        read(x1); read(y11); read(x2); read(y2);
        E = edg[x2][y2] - edg[x2][y11 - 1] - edg[x1 - 1][y2] + edg[x1 - 1][y11 - 1];
        E -= pr1[x1][y2] - pr1[x1][y11 - 1] + pr2[x2][y11] - pr2[x1 - 1][y11];
        V = num[x2][y2] - num[x2][y11 - 1] - num[x1 - 1][y2] + num[x1 - 1][y11 - 1];
        printf("%d\n", V - E);
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值