Submission #1193128

#TimeUsernameProblemLanguageResultExecution timeMemory
1193128LucaLucaMDango Maker (JOI18_dango_maker)C++20
100 / 100
1945 ms234620 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <bitset>
#include <random>
#pragma GCC optimize("Os")

using ll = long long;
#define debug(x) #x << " = " << x << '\n'

const int NMAX = 3000;

char a[NMAX][NMAX];
int vertical[NMAX][NMAX], horizontal[NMAX][NMAX];

std::bitset<NMAX * NMAX / 3> vis;
int l[NMAX * NMAX / 3], r[NMAX * NMAX / 3];

std::vector<std::pair<int, int>> edges;

bool cupleaza(int u) {
  vis[u] = true;

  int st = std::lower_bound(edges.begin(), edges.end(), std::pair<int, int>{u, 0}) - edges.begin();
  int dr = std::lower_bound(edges.begin(), edges.end(), std::pair<int, int>{u + 1, 0}) - edges.begin() - 1;

  for (int idv = st; idv <= dr; idv++) {
    int v = edges[idv].second;
    if (r[v] == -1) {
      r[v] = u;
      l[u] = v;
      return true;
    }
  }
  for (int idv = st; idv <= dr; idv++) {
    int v = edges[idv].second;
    if (!vis[r[v]] && cupleaza(r[v])) {
      l[u] = v;
      r[v] = u;
      return true;
    }
  }

  return false;
}

std::mt19937 rng(123);

int cntL, cntR;

int vertl[NMAX * NMAX / 3], vertr[NMAX * NMAX / 3];

int main() {
  #ifdef LOCAL
    freopen("input.txt", "r", stdin);
  #endif
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(0);

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

  for (int i = 0; i < n; i++) {
    std::string s;
    std::cin >> s;
    for (int j = 0; j < m; j++) {
      a[i][j] = s[j];
    }
  }

  int answer = 0;

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      vertical[i][j] = horizontal[i][j] = -1;
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j + 2 < m; j++) {
      if (a[i][j] == 'R' && a[i][j + 1] == 'G' && a[i][j + 2] == 'W') {
        vertl[cntL++] = i * m + j;
        vertical[i][j] = vertical[i][j + 1] = vertical[i][j + 2] = i * m + j;
      }
    }
  }

  for (int i = 0; i + 2 < n; i++) {
    for (int j = 0; j < m; j++) {
      if (a[i][j] == 'R' && a[i + 1][j] == 'G' && a[i + 2][j] == 'W') {
        vertr[cntR++] = i * m + j;
        horizontal[i][j] = horizontal[i + 1][j] = horizontal[i + 2][j] = i * m + j;
      }
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (vertical[i][j] != -1 && horizontal[i][j] != -1) {
        int x = std::lower_bound(vertl, vertl + cntL, vertical[i][j]) - vertl;
        int y = std::lower_bound(vertr, vertr + cntR, horizontal[i][j]) - vertr;
        edges.push_back({x, y});
      }
    }
  }

  edges.push_back({-1, -1});
  edges.push_back({1e9, 1e9});
  std::sort(edges.begin(), edges.end());
  edges.erase(std::unique(edges.begin(), edges.end()), edges.end());

  bool repeat = true;

  for (int i = 0; i < cntL; i++) {
    l[i] = -1;
  }
  for (int i = 0; i < cntR; i++) {
    r[i] = -1;
  }

  while (repeat) {
    repeat = false;
    for (int i = 0; i < cntL; i++) {
      vis[i] = false;
    }

    for (int i = 0; i < cntL; i++) {
      if (l[i] == -1 && cupleaza(i)) {
        answer++;
        repeat = true;
      }
    }
  }

  answer = cntL + cntR - answer;

  std::cout << answer;

  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...