# Bonus
Mỗi vùng liên thông chọn $1$ ô làm đại diện và đặt giá trị ô đó trên lưới bằng $1$, các ô còn lại đặt bằng $0$.
Với mỗi truy vấn:
- Tính tổng các ô $1$ nằm trong hình chữ nhật (HCN) của truy vấn đó (*)
- Các vùng liên thông thuộc HCN nhưng chưa thuộc (*) thì ô đại diện nằm bên ngoài HCN, ta có thể đếm các vùng này bằng cách xét các ô ở biên của HCN vì vùng liên thông đó phải cắt qua cạnh HCN.
Độ phức tạp: $O(Q \times (m+n))$
Code:
```cpp=
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
const int dx[] = {-1, 0, 0, 1};
const int dy[] = {0, -1, 1, 0};
int a[N][N], n, m, s[N][N], occ[N * N];
pair<int, int> p[N * N];
queue<pair<int, int>> que;
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
if (!p[a[i][j]].first) {
p[a[i][j]] = {i, j};
s[i][j]++;
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
s[i][j] += s[i - 1][j] +
s[i][j - 1] - s[i - 1][j - 1];
int q; cin >> q;
for (int tim = 1; tim <= q; tim++) {
int u, l, d, r;
cin >> u >> l >> d >> r;
int res = s[d][r] - s[d][l - 1]
- s[u - 1][r] + s[u - 1][l - 1];
int x, y;
for (int i = u; i <= d; i++) {
if (occ[a[i][l]] != tim) {
occ[a[i][l]] = tim;
tie(x, y) = p[a[i][l]];
if (x < u || x > d
|| y < l || y > r)
res++;
}
if (occ[a[i][r]] != tim) {
occ[a[i][r]] = tim;
tie(x, y) = p[a[i][r]];
if (x < u || x > d
|| y < l || y > r)
res++;
}
}
for (int j = l; j <= r; j++) {
if (occ[a[u][j]] != tim) {
occ[a[u][j]] = tim;
tie(x, y) = p[a[u][j]];
if (x < u || x > d
|| y < l || y > r)
res++;
}
if (occ[a[d][j]] != tim) {
occ[a[d][j]] = tim;
tie(x, y) = p[a[d][j]];
if (x < u || x > d
|| y < l || y > r)
res++;
}
}
cout << res << '\n';
}
}
```