题意:
有一个n*m的网格图,每个格子是蓝色或白色。四相邻的两个格子连一条边,保证蓝格子构成一个森林。
有q组询问,每次询问给出一个矩形,问矩形内蓝格子组成的联通块个数。
$1leq n,mleq 2000$
$1leq qleq200000$
题解:
结论:联通块数=点数-边数
二维前缀和乱搞,没了。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std;
10 typedef long long ll;
11 int n,m,q,x,y,_x,_y,a[2001][2001],pre[2001][2001],h[2001][2001],l[2001][2001],s[2001][2001];
12 char st[2001];
13 int main(){
14 memset(a,0,sizeof(a));
15 scanf("%d%d%d",&n,&m,&q);
16 for(int i=1;i<=n;i++){
17 scanf("%s",st+1);
18 for(int j=1;j<=m;j++){
19 a[i][j]=(st[j]=='1');
20 pre[i][j]=a[i][j]+pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];
21 l[i][j]=(a[i][j]==a[i-1][j]&&a[i][j])+l[i-1][j]+l[i][j-1]-l[i-1][j-1];
22 h[i][j]=(a[i][j]==a[i][j-1]&&a[i][j])+h[i-1][j]+h[i][j-1]-h[i-1][j-1];
23 }
24 }
25 while(q--){
26 scanf("%d%d%d%d",&x,&y,&_x,&_y);
27 printf("%d
",pre[_x][_y]-pre[x-1][_y]-pre[_x][y-1]+pre[x-1][y-1]-
28 (l[_x][_y]-l[x][_y]-l[_x][y-1]+l[x][y-1])-
29 (h[_x][_y]-h[x-1][_y]-h[_x][y]+h[x-1][y]));
30 }
31 return 0;
32 }