#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
using namespace std;
struct Pos {
int x, y;
bool operator==(const Pos& other) const {
return x == other.x && y == other.y;
}
};
// Custom hash function for Pos
struct PosHash {
size_t operator()(const Pos& pos) const {
return hash<int>()(pos.x) ^ (hash<int>()(pos.y) << 1);
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, k, q;
cin >> n >> m >> k >> q;
// Use unordered_set for efficient lookup, insertion, and deletion
unordered_set<Pos, PosHash> blocks;
// Read initial blocks
for (int i = 0; i < k; i++) {
int x, y;
cin >> x >> y;
blocks.insert({x, y});
}
// Function to check if a block can be removed
auto can_remove = [&](const Pos& pos, const unordered_set<Pos, PosHash>& current_blocks) -> bool {
// Check if we can grab left and right sides
bool left_free = current_blocks.find({pos.x, pos.y - 1}) == current_blocks.end();
bool right_free = current_blocks.find({pos.x, pos.y + 1}) == current_blocks.end();
// Check if we can grab top and bottom sides
bool top_free = current_blocks.find({pos.x - 1, pos.y}) == current_blocks.end();
bool bottom_free = current_blocks.find({pos.x + 1, pos.y}) == current_blocks.end();
return (left_free && right_free) || (top_free && bottom_free);
};
// Function to calculate maximum removable blocks
auto calculate_max_removable = [&]() -> int {
// Copy the blocks for simulation
unordered_set<Pos, PosHash> temp_blocks = blocks;
int count = 0;
bool made_progress = true;
while (made_progress && !temp_blocks.empty()) {
made_progress = false;
// Find blocks that can be removed
vector<Pos> to_remove;
for (const auto& pos : temp_blocks) {
if (can_remove(pos, temp_blocks)) {
to_remove.push_back(pos);
}
}
// Remove the blocks
for (const auto& pos : to_remove) {
temp_blocks.erase(pos);
count++;
made_progress = true;
}
}
return count;
};
// Calculate for initial configuration
vector<int> results;
results.push_back(calculate_max_removable());
// Process each move
for (int i = 0; i < q; i++) {
int x, y;
cin >> x >> y;
Pos pos = {x, y};
auto it = blocks.find(pos);
if (it == blocks.end()) {
// Add a block
blocks.insert(pos);
} else {
// Remove a block
blocks.erase(it);
}
// Calculate for the new configuration
results.push_back(calculate_max_removable());
}
// Output results
for (int result : results) {
cout << result << "\n";
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #include <iostream> #include <vector> #include <queue> #include <unordered_set> using namespace std; struct Pos { int x, y; bool operator==(const Pos& other) const { return x == other.x && y == other.y; } }; // Custom hash function for Pos struct PosHash { size_t operator()(const Pos& pos) const { return hash<int>()(pos.x) ^ (hash<int>()(pos.y) << 1); } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m, k, q; cin >> n >> m >> k >> q; // Use unordered_set for efficient lookup, insertion, and deletion unordered_set<Pos, PosHash> blocks; // Read initial blocks for (int i = 0; i < k; i++) { int x, y; cin >> x >> y; blocks.insert({x, y}); } // Function to check if a block can be removed auto can_remove = [&](const Pos& pos, const unordered_set<Pos, PosHash>& current_blocks) -> bool { // Check if we can grab left and right sides bool left_free = current_blocks.find({pos.x, pos.y - 1}) == current_blocks.end(); bool right_free = current_blocks.find({pos.x, pos.y + 1}) == current_blocks.end(); // Check if we can grab top and bottom sides bool top_free = current_blocks.find({pos.x - 1, pos.y}) == current_blocks.end(); bool bottom_free = current_blocks.find({pos.x + 1, pos.y}) == current_blocks.end(); return (left_free && right_free) || (top_free && bottom_free); }; // Function to calculate maximum removable blocks auto calculate_max_removable = [&]() -> int { // Copy the blocks for simulation unordered_set<Pos, PosHash> temp_blocks = blocks; int count = 0; bool made_progress = true; while (made_progress && !temp_blocks.empty()) { made_progress = false; // Find blocks that can be removed vector<Pos> to_remove; for (const auto& pos : temp_blocks) { if (can_remove(pos, temp_blocks)) { to_remove.push_back(pos); } } // Remove the blocks for (const auto& pos : to_remove) { temp_blocks.erase(pos); count++; made_progress = true; } } return count; }; // Calculate for initial configuration vector<int> results; results.push_back(calculate_max_removable()); // Process each move for (int i = 0; i < q; i++) { int x, y; cin >> x >> y; Pos pos = {x, y}; auto it = blocks.find(pos); if (it == blocks.end()) { // Add a block blocks.insert(pos); } else { // Remove a block blocks.erase(it); } // Calculate for the new configuration results.push_back(calculate_max_removable()); } // Output results for (int result : results) { cout << result << "\n"; } return 0; } |
English