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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>

std::vector<std::vector<int>> greedy(std::vector<std::vector<bool>> const& M) {
    int n = M.size();

    std::vector<std::vector<int>> X(n, std::vector<int>(n, -1));
    std::vector<std::vector<bool>> R(n, std::vector<bool>(n));
    std::vector<std::set<int>> A(n), B(n);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (!M[i][j]) {
                A[i].insert(j);
                B[j].insert(i);
            }
        }
    }

    std::priority_queue<std::pair<int, std::pair<int, int>>> Q;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (M[i][j]) {
                Q.push({-(A[i].size() + B[j].size()), {i, j}});
            }
        }
    }
    while (!Q.empty()) {
        auto [c, p] = Q.top();
        auto [x, y] = p;
        Q.pop();

        if (R[x][y]) continue;
        R[x][y] = 1;
        if (c == 0) continue;

        int a, b;
        if (A[x].size() > B[y].size()) {
            a = x;
            b = *A[x].begin();
            A[a].erase(b); B[b].erase(a);
            X[x][y] = 0; X[a][b] = 0;
            for (int k = 0; k < n; ++k) {
                if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}});
                if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}});
            }
        } else {
            a = *B[y].begin();
            b = y;
            A[a].erase(b); B[b].erase(a);
            X[x][y] = 1; X[a][b] = 1;
            for (int k = 0; k < n; ++k) {
                if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}});
                if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}});
            }
        }
    }
    for (int x = 0; x < n; ++x) {
        for (int y = 0; y < n; ++y) {
            if (!M[x][y] || R[x][y]) continue;
            if (A[x].size() == 0 && B[y].size() == 0) continue;

            int a, b;
            if (A[x].size() > B[y].size()) {
                a = x;
                b = *A[x].begin();
                A[a].erase(b); B[b].erase(a);
                X[x][y] = 0; X[a][b] = 0;
            } else {
                a = *B[y].begin();
                b = y;
                A[a].erase(b); B[b].erase(a);
                X[x][y] = 1; X[a][b] = 1;
            }
        }
    }
    return X;
}


typedef std::vector<std::set<int>> Graph;

std::pair<Graph, Graph> build_flow(std::vector<std::vector<bool>> const& B) {
    int n = B.size();

    int source = 0;
    int io_start = 1;
    int d1_start = io_start + n * n;
    int d2_start = d1_start + n;
    int sink = d2_start + n;

    std::vector<std::vector<int>> G = greedy(B);

    Graph E(sink + 1), R(sink + 1);

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (B[i][j]) {
                if (G[i][j] >= 0)
                    R[io_start + i * n + j].insert(source);
                else
                    E[source].insert(io_start + i * n + j);
                if (G[i][j] == 0)
                    R[d1_start + i].insert(io_start + i * n + j);
                else
                    E[io_start + i * n + j].insert(d1_start + i);
                if (G[i][j] == 1)
                    R[d2_start + j].insert(io_start + i * n + j);
                else
                    E[io_start + i * n + j].insert(d2_start + j);
            } else {
                if (G[i][j] == 0)
                    R[io_start + i * n + j].insert(d1_start + i);
                else
                    E[d1_start + i].insert(io_start + i * n + j);
                if (G[i][j] == 1)
                    R[io_start + i * n + j].insert(d2_start + j);
                else
                    E[d2_start + j].insert(io_start + i * n + j);
                if (G[i][j] >= 0)
                    R[sink].insert(io_start + i * n + j);
                else
                    E[io_start + i * n + j].insert(sink);
            }
        }
    }
    return {std::move(E), std::move(R)};
}

void switch_position(int n, Graph& E, Graph& R, int x, int y, bool new_val) {
    int source = 0;
    int io_start = 1;
    int d1_start = io_start + n * n;
    int d2_start = d1_start + n;
    int sink = d2_start + n;

    int p = io_start + x * n + y;
    if (!new_val) {
        if (R[p].find(0) != R[p].end()) {
            int v2, a, b;
            if (R[d1_start + x].find(p) != R[d1_start + x].end()) {
                v2 = d1_start + x;
                a = x;
                for (b = 0; b < n; ++b) {
                    if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break;
                }
            } else {
                v2 = d2_start + y;
                b = y;
                for (a = 0; a < n; ++a) {
                    if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break;
                }
            }
            R[sink].erase(io_start + a * n + b);
            E[io_start + a * n + b].insert(sink);
            R[io_start + a * n + b].erase(v2);
            E[v2].insert(io_start + a * n + b);
        }
    } else {
        if (R[sink].find(p) != R[sink].end()) {
            int v2, a, b;
            if (R[p].find(d1_start + x) != R[p].end()) {
                v2 = d1_start + x;
                a = x;
                for (b = 0; b < n; ++b) {
                    if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break;
                }
            } else {
                v2 = d2_start + y;
                b = y;
                for (a = 0; a < n; ++a) {
                    if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break;
                }
            }
            R[io_start + a * n + b].erase(0);
            E[0].insert(io_start + a * n + b);
            R[v2].erase(io_start + a * n + b);
            E[io_start + a * n + b].insert(v2);
        }
    }

    E[0].erase(p);
    R[p].erase(0);
    E[p].erase(sink);
    R[sink].erase(p);

    E[p].erase(d1_start + x);
    R[p].erase(d1_start + x);
    E[d1_start + x].erase(p);
    R[d1_start + x].erase(p);
    E[p].erase(d2_start + y);
    R[p].erase(d2_start + y);
    E[d2_start + y].erase(p);
    R[d2_start + y].erase(p);

    if (new_val) {
        E[0].insert(p);
        E[p].insert(d1_start + x);
        E[p].insert(d2_start + y);
    } else {
        E[p].insert(sink);
        E[d1_start + x].insert(p);
        E[d2_start + y].insert(p);
    }
}

int flow(Graph& E, Graph& R) {
    int const source = 0;
    int const sink = E.size() - 1;

    while (true) {
        std::map<int, int> L;

        //std::queue<std::pair<int, int>> Q;
        //Q.push({source, -1});
        std::vector<std::pair<int, int>> Q;
        Q.push_back({source, -1});

        while (!Q.empty()) {
            //auto [p, last] = Q.front(); Q.pop();
            auto [p, last] = Q.back(); Q.pop_back();

            if (L.find(p) != L.end()) continue;
            L[p] = last;
            if (p == sink) break;

            //for (int i : E[p]) Q.push({i, p});
            //for (int i : R[p]) Q.push({i, p});
            for (int i : E[p]) Q.push_back({i, p});
            for (int i : R[p]) Q.push_back({i, p});
        }

        if (L.find(sink) == L.end()) break;

        std::vector<int> path = {sink};
        while (path.back() != source) {
            path.push_back(L[path.back()]);
        }
        for (int i = 0; i < path.size() - 1; ++i) {
            int b = path[i], a = path[i + 1];
            if (E[a].find(b) != E[a].end()) {
                E[a].erase(b);
                R[b].insert(a);
            } else {
                R[a].erase(b);
                E[b].insert(a);
            }
        }
    }

    return R[sink].size();
}


int main() {
    std::ios::sync_with_stdio(false);

    int n, m, q;
    std::cin >> n >> m >> q;

    std::vector<std::vector<bool>> B(n, std::vector<bool>(n));

    for (int i = 0; i < m; ++i) {
        int a, b, c, d;
        std::cin >> a >> b >> c >> d;
        --a; --b; --c; --d;
        for (int x = a; x <= c; ++x) {
            for (int y = b; y <= d; ++y) {
                B[x][y] = !B[x][y];
            }
        }
    }

    auto [E, R] = build_flow(B);

    std::cout << flow(E, R) << "\n";
    for (int i = 0; i < q; ++i) {
        int x, y;
        std::cin >> x >> y;
        --x; --y;
        B[x][y] = !B[x][y];
        switch_position(n, E, R, x, y, B[x][y]);
        std::cout << flow(E, R) << "\n";
    }

    return 0;
}