AtCoder:C

C - Nuske vs Phantom Thnook

https://agc015.contest.atcoder.jp/tasks/agc015_c

题意:

  n*m的网格,每个格子可能是蓝色, 可能是白色,问一个子矩阵内,蓝色方格的联通块数。

  输入的数据中,保证蓝色点之间只有一条路径(或者没有)。

分析:

  因为任意蓝点之间只有一条路径,如果在相邻的蓝点之间连一条边后,也就是整张图没有环,在一个森林内,求一个些点构成的树的数量。

  结论:联通块数=总节点数-边数。

  因为,没加入一条边,会减少一个联通块,(即减少一棵树),加入了n条,就减去了n个。

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cctype>
 4 using namespace std;
 5 
 6 inline int read() {
 7     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 8     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 9 }
10 
11 const int N = 2005;
12 char s[N][N];
13 int s1[N][N], s2[N][N], s3[N][N];
14 
15 int main() {
16     int n = read(), m = read(), Q = read();
17     for (int i=1; i<=n; ++i) scanf("%s",s[i] + 1);
18     for (int i=1; i<=n; ++i) {
19         for (int j=1; j<=m; ++j) {
20             s1[i][j] = s1[i - 1][j] + s1[i][j - 1] - s1[i - 1][j - 1];
21             s2[i][j] = s2[i - 1][j] + s2[i][j - 1] - s2[i - 1][j - 1];
22             s3[i][j] = s3[i - 1][j] + s3[i][j - 1] - s3[i - 1][j - 1];
23             if (s[i][j] == '1') {
24                 s1[i][j] ++;
25                 if (s[i][j] == s[i - 1][j]) s2[i][j] ++;
26                 if (s[i][j] == s[i][j - 1]) s3[i][j] ++;
27             }
28         }
29     }
30     while (Q--) {
31         int a1 = read(), b1 = read(), a2 = read(), b2 = read();
32         int t1 = s1[a2][b2] - s1[a2][b1 - 1] - s1[a1 - 1][b2] + s1[a1 - 1][b1 - 1];
33         int t2 = s2[a2][b2] - s2[a2][b1 - 1] - s2[a1][b2] + s2[a1][b1 - 1];
34         int t3 = s3[a2][b2] - s3[a2][b1] - s3[a1 - 1][b2] + s3[a1 - 1][b1];
35         printf("%d
",t1 - t2 - t3);
36     }
37     return 0;
38 }
原文地址:https://www.cnblogs.com/mjtcn/p/9707935.html