Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <vector>
- #include <cassert>
- #include <functional>
- #include <memory>
- #include "../atcoder/segtree"
- #include "../atcoder/lazysegtree.hpp"
- using namespace std;
- typedef pair<int, int> ii;
- typedef long long int64;
- typedef vector<int> vi;
- #define pb push_back
- #define all(v) (v).begin(),(v).end()
- #define sz(v) ((int)(v).size())
- int IntSum(int x, int y) {
- return x + y;
- }
- int IntMin(int x, int y) {
- return min(x, y);
- }
- int IntZero() {
- return 0;
- }
- int IntInf() {
- return 1000 * 1000 * 1000;
- }
- using MegaTree = atcoder::lazy_segtree<int, IntMin, IntInf, int, IntSum, IntSum, IntZero>;
- struct DownSolver {
- vector<vi> a;
- int k;
- int n, m;
- vector<unique_ptr<atcoder::segtree<int, IntSum, IntZero>>> topk;
- unique_ptr<MegaTree> rows;
- void Flip(int x, int y) {
- int cur_sum = topk[y]->prod(0, x + 2);
- int l = topk[y]->max_right(0, [this](int x) { return x <= this->k; }) - 1;
- int delta = a[x][y] == 1 ? -1 : 1;
- a[x][y] = 1 - a[x][y];
- topk[y]->set(x + 1, a[x][y]);
- int r = topk[y]->max_right(0, [this](int x) { return x <= this->k; }) - 1;
- assert(l >= 0);
- assert(r >= 0);
- if (delta == 1) {
- if (r < n && a[r][y]) ++r;
- if (l > 0 && l < n && a[l - 1][y]) --l;
- if (l > r) {
- rows->apply(r + 1, l + 1, delta);
- }
- if ((x < r || x >= l) && cur_sum <= k) {
- rows->apply(x + 1, x + 2, delta);
- }
- } else {
- if (r < n && r > 0 && a[r - 1][y]) --r;
- if (l < n && a[l][y]) ++l;
- if (r > l)
- rows->apply(l + 1, r + 1, delta);
- if ((x < l || x >= r) && cur_sum <= k + 1) {
- rows->apply(x + 1, x + 2, delta);
- }
- }
- }
- void Init(const vector<vi>& _a, int _k) {
- this->a = _a;
- this->k = _k;
- n = sz(a);
- m = sz(a[0]);
- rows.reset(new MegaTree(n + 10));
- for (int i = 0; i < m; ++i) {
- auto* tree = new atcoder::segtree<int, IntSum, IntZero>(n + 10);
- topk.emplace_back(unique_ptr<atcoder::segtree<int, IntSum, IntZero>>(tree));
- }
- a.push_back(vi(m, 0));
- vi sum(m, 0);
- for (int i = 0; i <= n; ++i) {
- for (int j = 0; j < m; ++j) {
- if (a[i][j]) {
- topk[j]->set(i + 1, 1);
- }
- }
- if (i < n) {
- for (int j = 0; j < m; ++j)
- sum[j] += a[i][j];
- }
- if (i >= k) {
- int cur = i - k;
- for (int j = 0; j < m; ++j) {
- if (a[i][j] || sum[j] > k) ++cur;
- }
- rows->set(i + 1, cur);
- }
- }
- }
- int Res() const {
- return min(m + 1, rows->prod(0, n + 2));
- }
- };
- class TaskC {
- public:
- void solve(std::istream& in, std::ostream& out) {
- int num_tests;
- in >> num_tests;
- for (int i = 0; i < num_tests; ++i) {
- cerr << "Case " << i << "\n";
- cerr.flush();
- out << "Case #" << (i + 1) << ": ";
- doSolve(in, out);
- }
- }
- vector<vi> a;
- void doSolve(std::istream& in, std::ostream& out) {
- int n, m, k, q;
- in >> n >> m >> k >> q;
- --k;
- a = vector<vi>(n, vi(m, 0));
- for (int i = 0; i < n; ++i) {
- string s;
- in >> s;
- for (int j = 0; j < m; ++j) {
- a[i][j] = (s[j] == 'X' ? 1 : 0);
- }
- }
- DownSolver straight, rev;
- straight.Init(a, k);;
- reverse(all(a));
- rev.Init(a, n - k - 1);
- int64 res = 0;
- for (int i = 0; i < q; ++i) {
- int x, y;
- in >> x >> y;
- --x, --y;
- straight.Flip(x, y);
- rev.Flip(n - x - 1, y);
- res += min(straight.Res(), rev.Res());
- }
- out << res << "\n";
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement