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
#include <bits/stdc++.h>
using namespace std;

#define FOR(i, l, r) for(int i = (l); i <= (r); ++i)
#define REP(i, n) FOR(i, 0, (n) - 1)
#define ssize(x) int(x.size())
#ifdef DEBUG
auto &operator << (auto &o, pair<auto, auto> p) {
	return o << "(" << p.first << ", " << p.second << ")";
}
auto operator << (auto &o, auto x) -> decltype(x.end(), o) {
	o << "{"; int i = 0;
	for (auto e : x) o << ","+!i++ << e;
	return o << "}";
}
ostream& operator << (ostream &o, vector<vector<bool>> board) {
	o << '\n';
	for (auto b : board) {
		string row = "";
		for (bool b_i : b)
			row += (b_i ? "#" : ".");
		o << row << '\n';;
	}
	return o;
}
#define debug(X...) cerr << "["#X"]: ", [](auto ...$) {((cerr << $ << "; "), ...) << endl;}(X)
#else
#define debug(...) {}
#endif

int n, m;
set<pair<int, int>> org_points;

vector<pair<int, int>> get_neis(int x, int y) {
	return {
		{x - 1, y},
		{x + 1, y},
		{x,  y - 1},
		{x, y + 1}
	};
}

int solve() {
	auto points = org_points;

	auto exists = [&](int x, int y) {
		return points.contains(pair(x, y));
	};

	auto can_be_taken = [&](int i, int j) {
		if ((i == 0 or !exists(i - 1, j)) 
				and (i == n - 1 or !exists(i + 1, j)))
			return true;

		if ((j == 0 or !exists(i, j - 1))
				and (j == m - 1 or !exists(i, j + 1)))
			return true;

		return false;
	};

	deque<pair<int, int>> Q = {};
	set<pair<int, int>> visited = {};

	REP (i, n) REP (j, m) {
		if (exists(i, j) and can_be_taken(i, j)) {
			visited.emplace(i, j);
			Q.emplace_back(i, j);
		}
	}

	int answer = 0;
	while (!Q.empty()) {
		auto [i, j] = Q.front();
		Q.pop_front();
		points.erase(pair(i, j));
		++answer;

		for (auto [x, y] : get_neis(i, j)) {
			if (x < 0 or x >= n or y < 0 or y >= m)
				continue;

			if (exists(x, y) and !visited.contains({x, y})
					and can_be_taken(x, y)) {
				visited.emplace(x, y);
				Q.emplace_back(x, y);
			}
		}
	}

	return answer;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	int k, q;
	cin >> n >> m >> k >> q;

	REP (i, k) {
		int x, y;
		cin >> x >> y;
		--x, --y;
		org_points.emplace(x, y);
	}

	cout << solve() << '\n';

	while (q--) {
		int x, y;
		cin >> x >> y;
		--x, --y;

		if (org_points.contains({x, y}))
			org_points.erase({x, y});
		else
			org_points.emplace(x, y);
		cout << solve() << '\n';
	}
}