Hướng giải của Lật Bóng Đèn Ma Trận
Nhớ rằng hướng dẫn giải này chỉ nên sử dụng khi bế tắc, và tuyệt đối không nên sao chép mã nguồn kèm theo. Hãy tôn trọng tác giả bài tập và người viết hướng dẫn giải.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Tác giả:
Hướng dẫn giải
Trò chơi yêu cầu bật/tắt (lật trạng thái) một bóng đèn đơn lẻ và đếm số lượng bóng đèn đang bật trong một khu vực hình chữ nhật.
- Ta sử dụng mảng phụ
current_statekích thước \(N \times M\) để ghi nhớ trạng thái tắt/bật (0/1) của mỗi bóng đèn. - Khi lật bóng đèn tại \((x, y)\):
- Nếu bóng đang tắt (0), ta đổi trạng thái thành bật (1) và thực hiện cập nhật cộng thêm
1vào BIT 2D. - Nếu bóng đang bật (1), ta đổi trạng thái thành tắt (0) và cập nhật trừ đi
1(cộng-1) vào BIT 2D.
- Nếu bóng đang tắt (0), ta đổi trạng thái thành bật (1) và thực hiện cập nhật cộng thêm
- Để đếm số bóng đèn bật sáng trong khu vực hình chữ nhật từ \((x_1, y_1)\) đến \((x_2, y_2)\), ta thực hiện truy vấn Range Query bằng nguyên lý Bao hàm - Loại trừ trên BIT 2D.
Mã nguồn C++ mẫu
#include <bits/stdc++.h>
using namespace std;
int n, m, q;
vector<vector<int>> bit;
vector<vector<int>> current_state;
void update(int x, int y, int val) {
for (int i = x; i <= n; i += i & -i) {
for (int j = y; j <= m; j += j & -j) {
bit[i][j] += val;
}
}
}
int query(int x, int y) {
int s = 0;
for (int i = x; i > 0; i -= i & -i) {
for (int j = y; j > 0; j -= j & -j) {
s += bit[i][j];
}
}
return s;
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL);
if (!(cin >> n >> m >> q)) return 0;
bit.assign(n + 1, vector<int>(m + 1, 0));
current_state.assign(n + 1, vector<int>(m + 1, 0));
while (q--) {
int t; cin >> t;
if (t == 1) {
int x, y; cin >> x >> y;
if (current_state[x][y] == 0) {
current_state[x][y] = 1;
update(x, y, 1);
} else {
current_state[x][y] = 0;
update(x, y, -1);
}
} else {
int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
cout << query(x2, y2) - query(x1 - 1, y2) - query(x2, y1 - 1) + query(x1 - 1, y1 - 1) << "\n";
}
}
}
Nhận xét