Nuske vs Phantom Thnook(前缀和+联通性)
题目描述
Phantom Thnook, Nuske’s eternal rival, gives Q queries to Nuske. The i-th query consists of four integers xi,1, yi,1, xi,2 and yi,2 and asks him the following: when the rectangular region of the grid bounded by (and including) the xi,1-th row, xi,2-th row, yi,1-th column and yi,2-th column is cut out, how many connected components consisting of blue squares there are in the region?
Process all the queries.
Constraints
1≤N,M≤2000
1≤Q≤200000
Si,j is either 0 or 1.
Si,j satisfies the condition explained in the statement.
1≤xi,1≤xi,2≤N(1≤i≤Q)
1≤yi,1≤yi,2≤M(1≤i≤Q)
输入
N M Q
S1,1..S1,M
:
SN,1..SN,M
x1,1 yi,1 xi,2 yi,2
:
xQ,1 yQ,1 xQ,2 yQ,2
输出
样例输入 Copy
3 4 4
1101
0110
1101
1 1 3 4
1 1 3 1
2 2 3 4
1 2 2 4
样例输出 Copy
3
2
2
2
提示
![](https://i-blog.csdnimg.cn/blog_migrate/805a7d32bbe2f01d81bf37ca570895bf.png)
In the first query, the whole grid is specified. There are three components consisting of blue squares, and thus 3 should be printed.
In the second query, the region within the red frame is specified. There are two components consisting of blue squares, and thus 2 should be printed. Note that squares that belong to the same component in the original grid may belong to different components.
思路:因为一个点走到另一个点最多只有一条路,所以一个联通的块,n个点,n-1条边。
只需前缀求点数和边数。用点数减去边数。边数通过求x,y方向上面的边。求x,时,y是不会变的。同理求y也是。
#pragma GCC optimize(3 , "Ofast" , "inline")
#include <bits/stdc++.h>
#define rep(i , a , b) for(register ll i=(a);i<=(b);i++)
#define rop(i , a , b) for(register ll i=(a);i<(b);i++)
#define per(i , a , b) for(register ll i=(a);i>=(b);i--)
#define por(i , a , b) for(register ll i=(a);i>(b);i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll , ll> pi;
template<class T>
inline void read (T &x) {
x = 0;
int sign = 1;
char c = getchar ();
while (c < '0' || c > '9') {
if ( c == '-' ) sign = - 1;
c = getchar ();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar ();
}
x = x * sign;
}
const int maxn = 2e3 + 10;
const int inf = int (1e9);
const ll INF = ll(1e18);
int n,m,q;
char e[maxn][maxn];
int s1[maxn][maxn];
int s2[maxn][maxn];
int s3[maxn][maxn];
int main () {
read(n);read(m);read(q);
rep(i,1,n) {
scanf("%s",e[i]+1);
}
rep(i,1,n) {
rep(j,1,m) {
if(e[i][j]=='1') s1[i][j]=1;
s1[i][j]+=s1[i-1][j]+s1[i][j-1]-s1[i-1][j-1];
}
}
rep(i,1,n) {
rep(j,1,m) {
if(e[i][j]=='1'&&e[i-1][j]=='1') s2[i][j]=1;
else s2[i][j]=0;
if(e[i][j]=='1'&&e[i][j-1]=='1') s3[i][j]=1;
else s3[i][j]=0;
s2[i][j]+=s2[i-1][j]+s2[i][j-1]-s2[i-1][j-1];
s3[i][j]+=s3[i-1][j]+s3[i][j-1]-s3[i-1][j-1];
}
}
rep(i,1,q) {
int x1,y1,x2,y2;
read(x1);read(y1);read(x2);read(y2);
int ans1 = s1[x2][y2]-s1[x2][y1-1]-s1[x1-1][y2]+s1[x1-1][y1-1];
int ans2 = s2[x2][y2]-s2[x2][y1-1]-s2[x1][y2]+s2[x1][y1-1];
int ans3 = s3[x2][y2]-s3[x2][y1]-s3[x1-1][y2]+s3[x1-1][y1];
printf("%d\n",ans1-ans2-ans3);
}
return 0;
}