#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; } |