#include <iostream>
#include <queue>
#include <unordered_set>
using namespace std;
using Brick = pair<long long, long long>;
struct BrickHash {
std::size_t operator()(const Brick &k) const {
return hash<long long>()(k.first ^ k.second << 32);
}
};
using BrickSet = unordered_set<Brick, BrickHash>;
Brick left(Brick brick) {
return {brick.first, brick.second - 1};
}
Brick right(Brick brick) {
return {brick.first, brick.second + 1};
}
Brick up(Brick brick) {
return {brick.first - 1, brick.second};
}
Brick down(Brick brick) {
return {brick.first + 1, brick.second};
}
bool present(Brick brick, const BrickSet &bricks, const BrickSet &removed) {
return !removed.contains(brick) && bricks.contains(brick);
}
bool canRemove(Brick brick, const BrickSet &bricks, const BrickSet &removed) {
return (!present(left(brick), bricks, removed) && !present(right(brick), bricks, removed)) || (!present(up(brick), bricks, removed) && !present(down(brick), bricks, removed));
}
BrickSet removed;
void printRemoved() {
for (auto [a, b] : removed) {
cout << "(" << a << ", " << b << ") ";
}
cout << "\n";
}
void addNeighborsToQueue(const BrickSet &bricks, const BrickSet &removed, Brick brick, queue<Brick> &bfs) {
if (present(left(brick), bricks, removed)) {
bfs.push(left(brick));
}
if (present(right(brick), bricks, removed)) {
bfs.push(right(brick));
}
if (present(up(brick), bricks, removed)) {
bfs.push(up(brick));
}
if (present(down(brick), bricks, removed)) {
bfs.push(down(brick));
}
}
int solve(const BrickSet &bricks, bool useStartBricks = false, BrickSet startBricks = {}) {
queue<Brick> bfs;
if (useStartBricks) {
for (auto brick : startBricks) {
bfs.push(brick);
}
} else {
for (auto brick : bricks) {
bfs.push(brick);
}
}
while (!bfs.empty()) {
auto brick = bfs.front();
bfs.pop();
if (canRemove(brick, bricks, removed)) {
removed.insert(brick);
addNeighborsToQueue(bricks, removed, brick, bfs);
}
}
return size(removed);
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, k, q;
cin >> n >> m >> k >> q;
BrickSet bricks;
for (int i = 0; i < k; ++i) {
int x, y;
cin >> x >> y;
bricks.insert({x, y});
}
cout << solve(bricks) << '\n';
for (int i = 0; i < q; ++i) {
Brick newBrick;
cin >> newBrick.first >> newBrick.second;
if (bricks.contains(newBrick)) {
bricks.erase(newBrick);
removed.erase(newBrick);
if (removed.contains(newBrick)) {
cout << size(removed) << '\n';
} else {
BrickSet startBricks;
if (present(left(newBrick), bricks, removed) && canRemove(left(newBrick), bricks, removed)) {
startBricks.insert(left(newBrick));
}
if (present(right(newBrick), bricks, removed) && canRemove(right(newBrick), bricks, removed)) {
startBricks.insert(right(newBrick));
}
if (present(up(newBrick), bricks, removed) && canRemove(up(newBrick), bricks, removed)) {
startBricks.insert(up(newBrick));
}
if (present(down(newBrick), bricks, removed) && canRemove(down(newBrick), bricks, removed)) {
startBricks.insert(down(newBrick));
}
cout << solve(bricks, true, startBricks) << '\n';
}
} else {
bricks.insert(newBrick);
if (canRemove(newBrick, bricks, {})) {
removed.insert(newBrick);
cout << size(removed) << "\n";
} else {
BrickSet startBricks;
queue<Brick> tmp;
tmp.push(newBrick);
while (!tmp.empty()) {
auto brick = tmp.front();
tmp.pop();
if (!canRemove(brick, bricks, {})) {
removed.erase(brick);
startBricks.insert(brick);
if (present(left(brick), removed, {})) {
tmp.push(left(brick));
}
if (present(right(brick), removed, {})) {
tmp.push(right(brick));
}
if (present(up(brick), removed, {})) {
tmp.push(up(brick));
}
if (present(down(brick), removed, {})) {
tmp.push(down(brick));
}
}
}
cout << solve(bricks, true, startBricks) << '\n';
}
}
}
}
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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #include <iostream> #include <queue> #include <unordered_set> using namespace std; using Brick = pair<long long, long long>; struct BrickHash { std::size_t operator()(const Brick &k) const { return hash<long long>()(k.first ^ k.second << 32); } }; using BrickSet = unordered_set<Brick, BrickHash>; Brick left(Brick brick) { return {brick.first, brick.second - 1}; } Brick right(Brick brick) { return {brick.first, brick.second + 1}; } Brick up(Brick brick) { return {brick.first - 1, brick.second}; } Brick down(Brick brick) { return {brick.first + 1, brick.second}; } bool present(Brick brick, const BrickSet &bricks, const BrickSet &removed) { return !removed.contains(brick) && bricks.contains(brick); } bool canRemove(Brick brick, const BrickSet &bricks, const BrickSet &removed) { return (!present(left(brick), bricks, removed) && !present(right(brick), bricks, removed)) || (!present(up(brick), bricks, removed) && !present(down(brick), bricks, removed)); } BrickSet removed; void printRemoved() { for (auto [a, b] : removed) { cout << "(" << a << ", " << b << ") "; } cout << "\n"; } void addNeighborsToQueue(const BrickSet &bricks, const BrickSet &removed, Brick brick, queue<Brick> &bfs) { if (present(left(brick), bricks, removed)) { bfs.push(left(brick)); } if (present(right(brick), bricks, removed)) { bfs.push(right(brick)); } if (present(up(brick), bricks, removed)) { bfs.push(up(brick)); } if (present(down(brick), bricks, removed)) { bfs.push(down(brick)); } } int solve(const BrickSet &bricks, bool useStartBricks = false, BrickSet startBricks = {}) { queue<Brick> bfs; if (useStartBricks) { for (auto brick : startBricks) { bfs.push(brick); } } else { for (auto brick : bricks) { bfs.push(brick); } } while (!bfs.empty()) { auto brick = bfs.front(); bfs.pop(); if (canRemove(brick, bricks, removed)) { removed.insert(brick); addNeighborsToQueue(bricks, removed, brick, bfs); } } return size(removed); } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m, k, q; cin >> n >> m >> k >> q; BrickSet bricks; for (int i = 0; i < k; ++i) { int x, y; cin >> x >> y; bricks.insert({x, y}); } cout << solve(bricks) << '\n'; for (int i = 0; i < q; ++i) { Brick newBrick; cin >> newBrick.first >> newBrick.second; if (bricks.contains(newBrick)) { bricks.erase(newBrick); removed.erase(newBrick); if (removed.contains(newBrick)) { cout << size(removed) << '\n'; } else { BrickSet startBricks; if (present(left(newBrick), bricks, removed) && canRemove(left(newBrick), bricks, removed)) { startBricks.insert(left(newBrick)); } if (present(right(newBrick), bricks, removed) && canRemove(right(newBrick), bricks, removed)) { startBricks.insert(right(newBrick)); } if (present(up(newBrick), bricks, removed) && canRemove(up(newBrick), bricks, removed)) { startBricks.insert(up(newBrick)); } if (present(down(newBrick), bricks, removed) && canRemove(down(newBrick), bricks, removed)) { startBricks.insert(down(newBrick)); } cout << solve(bricks, true, startBricks) << '\n'; } } else { bricks.insert(newBrick); if (canRemove(newBrick, bricks, {})) { removed.insert(newBrick); cout << size(removed) << "\n"; } else { BrickSet startBricks; queue<Brick> tmp; tmp.push(newBrick); while (!tmp.empty()) { auto brick = tmp.front(); tmp.pop(); if (!canRemove(brick, bricks, {})) { removed.erase(brick); startBricks.insert(brick); if (present(left(brick), removed, {})) { tmp.push(left(brick)); } if (present(right(brick), removed, {})) { tmp.push(right(brick)); } if (present(up(brick), removed, {})) { tmp.push(up(brick)); } if (present(down(brick), removed, {})) { tmp.push(down(brick)); } } } cout << solve(bricks, true, startBricks) << '\n'; } } } } |
English