結果

問題 No.421 しろくろチョコレート
ユーザー yuruhiyayuruhiya
提出日時 2020-08-06 19:52:59
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 3 ms / 2,000 ms
コード長 24,519 bytes
コンパイル時間 2,529 ms
コンパイル使用メモリ 209,804 KB
最終ジャッジ日時 2025-01-12 15:28:58
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 65
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)
using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1e9;
constexpr long long inf_ll = 1e18, MOD = 1000000007;
constexpr long double PI = M_PI, EPS = 1e-12;
// --- input --- //
#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Input {
static int gc() {
return getchar_unlocked();
}
template <class T> static void i(T& v) {
cin >> v;
}
static void i(char& v) {
while (isspace(v = gc()))
;
}
static void i(bool& v) {
v = in<char>() != '0';
}
static void i(string& v) {
v.clear();
char c;
for (i(c); !isspace(c); c = gc()) v += c;
}
static void i(int& v) {
bool neg = false;
v = 0;
char c;
i(c);
if (c == '-') {
neg = true;
c = gc();
}
for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
if (neg) v = -v;
}
static void i(long long& v) {
bool neg = false;
v = 0;
char c;
i(c);
if (c == '-') {
neg = true;
c = gc();
}
for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
if (neg) v = -v;
}
static void i(double& v) {
double dp = 1;
bool neg = false, adp = false;
v = 0;
char c;
i(c);
if (c == '-') {
neg = true;
c = gc();
}
for (; isdigit(c) || c == '.'; c = gc()) {
if (c == '.')
adp = true;
else if (adp)
v += (c - '0') * (dp *= 0.1);
else
v = v * 10 + (c - '0');
}
if (neg) v = -v;
}
static void i(long double& v) {
long double dp = 1;
bool neg = false, adp = false;
v = 0;
char c;
i(c);
if (c == '-') {
neg = true;
c = gc();
}
for (; isdigit(c) || c == '.'; c = gc()) {
if (c == '.')
adp = true;
else if (adp)
v += (c - '0') * (dp *= 0.1);
else
v = v * 10 + (c - '0');
}
if (neg) v = -v;
}
template <class T, class U> static void i(pair<T, U>& v) {
i(v.first);
i(v.second);
}
template <class T> static void i(vector<T>& v) {
for (auto& e : v) i(e);
}
template <size_t N = 0, class T> static void input_tuple(T& v) {
if constexpr (N < tuple_size_v<T>) {
i(get<N>(v));
input_tuple<N + 1>(v);
}
}
template <class... T> static void i(tuple<T...>& v) {
input_tuple(v);
}
struct InputV {
int n, m;
InputV(int _n) : n(_n), m(0) {}
InputV(const pair<int, int>& nm) : n(nm.first), m(nm.second) {}
template <class T> operator vector<T>() {
vector<T> v(n);
i(v);
return v;
}
template <class T> operator vector<vector<T>>() {
vector<vector<T>> v(n, vector<T>(m));
i(v);
return v;
}
};
public:
static string read_line() {
string v;
char c;
for (i(c); c != '\n' && c != '\0'; c = gc()) v += c;
return v;
}
template <class T> static T in() {
T v;
i(v);
return v;
}
template <class T> operator T() const {
return in<T>();
}
int operator--(int) const {
return in<int>() - 1;
}
InputV operator[](int n) const {
return InputV(n);
}
InputV operator[](const pair<int, int>& n) const {
return InputV(n);
}
void operator()() const {}
template <class H, class... T> void operator()(H&& h, T&&... t) const {
i(h);
operator()(forward<T>(t)...);
}
private:
template <template <class...> class, class...> struct Multiple;
template <template <class...> class V, class Head, class... Tail> struct Multiple<V, Head, Tail...> {
template <class... Args> using vec = V<vector<Head>, Args...>;
using type = typename Multiple<vec, Tail...>::type;
};
template <template <class...> class V> struct Multiple<V> { using type = V<>; };
template <class... T> using multiple_t = typename Multiple<tuple, T...>::type;
template <size_t N = 0, class T> void in_multiple(T& t) const {
if constexpr (N < tuple_size_v<T>) {
auto& vec = get<N>(t);
using V = typename remove_reference_t<decltype(vec)>::value_type;
vec.push_back(in<V>());
in_multiple<N + 1>(t);
}
}
public:
template <class... T> auto multiple(int H) const {
multiple_t<T...> res;
while (H--) in_multiple(res);
return res;
}
} in;
#define input(T) Input::in<T>()
#define INT input(int)
#define LL input(long long)
#define STR input(string)
#define inputs(T, ...) \
T __VA_ARGS__; \
in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)
// --- output --- //
struct BoolStr {
const char *t, *f;
BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
const char *d, *l;
DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"), no_endl(" ", "");
class Output {
BoolStr B{Yes};
DivStr D{spc};
void p(int v) const {
if (v < 0) putchar_unlocked('-'), v = -v;
char b[10];
int i = 0;
while (v) b[i++] = '0' + v % 10, v /= 10;
if (!i) b[i++] = '0';
while (i--) putchar_unlocked(b[i]);
}
void p(long long v) const {
if (v < 0) putchar_unlocked('-'), v = -v;
char b[20];
int i = 0;
while (v) b[i++] = '0' + v % 10, v /= 10;
if (!i) b[i++] = '0';
while (i--) putchar_unlocked(b[i]);
}
void p(bool v) const {
p(v ? B.t : B.f);
}
void p(char v) const {
putchar_unlocked(v);
}
void p(const char* v) const {
fwrite_unlocked(v, 1, strlen(v), stdout);
}
void p(double v) const {
printf("%.20f", v);
}
void p(long double v) const {
printf("%.20Lf", v);
}
template <class T> void p(const T& v) const {
cout << v;
}
template <class T, class U> void p(const pair<T, U>& v) const {
p(v.first);
p(D.d);
p(v.second);
}
template <class T> void p(const vector<T>& v) const {
rep(i, sz(v)) {
if (i) p(D.d);
p(v[i]);
}
}
template <class T> void p(const vector<vector<T>>& v) const {
rep(i, sz(v)) {
if (i) p(D.l);
p(v[i]);
}
}
public:
Output& operator()() {
p(D.l);
return *this;
}
template <class H> Output& operator()(H&& h) {
p(h);
p(D.l);
return *this;
}
template <class H, class... T> Output& operator()(H&& h, T&&... t) {
p(h);
p(D.d);
return operator()(forward<T>(t)...);
}
template <class It> Output& range(const It& l, const It& r) {
for (It i = l; i != r; i++) {
if (i != l) p(D.d);
p(*i);
}
p(D.l);
return *this;
}
template <class T> Output& range(const T& a) {
range(a.begin(), a.end());
return *this;
}
template <class... T> void exit(T&&... t) {
operator()(forward<T>(t)...);
std::exit(EXIT_SUCCESS);
}
Output& flush() {
fflush_unlocked(stdout);
return *this;
}
Output& set(const BoolStr& b) {
B = b;
return *this;
}
Output& set(const DivStr& d) {
D = d;
return *this;
}
Output& set(const char* t, const char* f) {
B = BoolStr(t, f);
return *this;
}
} out;
// --- step --- //
template <class T> struct Step {
class It {
T a, b, c;
public:
constexpr It() : a(T()), b(T()), c(T()) {}
constexpr It(T _b, T _c, T _s) : a(_b), b(_c), c(_s) {}
constexpr It& operator++() {
--b;
a += c;
return *this;
}
constexpr It operator++(int) {
It tmp = *this;
--b;
a += c;
return tmp;
}
constexpr const T& operator*() const {
return a;
}
constexpr const T* operator->() const {
return &a;
}
constexpr bool operator==(const It& i) const {
return b == i.b;
}
constexpr bool operator!=(const It& i) const {
return !(b == i.b);
}
constexpr T start() const {
return a;
}
constexpr T count() const {
return b;
}
constexpr T step() const {
return c;
}
};
constexpr Step(T b, T c, T s) : be(b, c, s) {}
constexpr It begin() const {
return be;
}
constexpr It end() const {
return en;
}
constexpr T start() const {
return be.start();
}
constexpr T count() const {
return be.count();
}
constexpr T step() const {
return be.step();
}
constexpr T sum() const {
return start() * count() + step() * (count() * (count() - 1) / 2);
}
operator vector<T>() const {
return to_a();
}
template <class F> void each(const F& f) const {
for (T i : *this) f(i);
}
auto to_a() const {
vector<T> res;
res.reserve(count());
each([&](T i) { res.push_back(i); });
return res;
}
template <class F, class U = invoke_result_t<F, T>> auto map(const F& f) const {
vector<U> res;
res.reserve(count());
each([&](T i) { res.push_back(f(i)); });
return res;
}
template <class F> auto select(const F& f) const {
vector<T> res;
each([&](T i) {
if (f(i)) res.push_back(i);
});
return res;
}
template <class F> int count_if(const F& f) const {
int res = 0;
each([&](T i) {
if (f(i)) ++res;
});
return res;
}
template <class F> optional<T> find_if(const F& f) const {
for (T i : *this)
if (f(i)) return i;
return nullopt;
}
template <class F> auto max_by(const F& f) const {
auto v = map(f);
return *max_element(v.begin(), v.end());
}
template <class F> auto min_by(const F& f) const {
auto v = map(f);
return *min_element(v.begin(), v.end());
}
template <class F> bool all_of(const F& f) const {
for (T i : *this)
if (!f(i)) return false;
return true;
}
template <class F> bool any_of(const F& f) const {
for (T i : *this)
if (f(i)) return true;
return false;
}
template <class F, class U = invoke_result_t<F, T>> auto sum(const F& f) const {
U res = 0;
each([&](T i) { res += static_cast<U>(f(i)); });
return res;
}
using value_type = T;
using iterator = It;
private:
It be, en;
};
template <class T> inline constexpr auto step(T a) {
return Step<T>(0, a, 1);
}
template <class T> inline constexpr auto step(T a, T b) {
return Step<T>(a, b - a, 1);
}
template <class T> inline constexpr auto step(T a, T b, T c) {
return Step<T>(a, a < b ? (b - a - 1) / c + 1 : 0, c);
}
// --- functions --- //
inline namespace {
template <class T> inline void Sort(T& a) {
sort(all(a));
}
template <class T> inline void RSort(T& a) {
sort(rall(a));
}
template <class T, class F> inline void Sort(T& a, const F& f) {
sort(all(a), f);
}
template <class T, class F> inline void RSort(T& a, const F& f) {
sort(rall(a), f);
}
template <class T> inline T Sorted(T a) {
Sort(a);
return a;
}
template <class T> inline T RSorted(T a) {
RSort(a);
return a;
}
template <class T, class F> inline T Sorted(T& a, const F& f) {
Sort(a, f);
return a;
}
template <class T, class F> inline T RSorted(T& a, const F& f) {
RSort(a, f);
return a;
}
template <class T, class F> inline void SortBy(T& a, const F& f) {
sort(all(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
}
template <class T, class F> inline void RSortBy(T& a, const F& f) {
sort(rall(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
}
template <class T> inline void Reverse(T& a) {
reverse(all(a));
}
template <class T> inline void Unique(T& a) {
a.erase(unique(all(a)), a.end());
}
template <class T> inline void Uniq(T& a) {
Sort(a);
Unique(a);
}
template <class T> inline void Rotate(T& a, int left) {
rotate(a.begin(), a.begin() + left, a.end());
}
template <class T> inline T Reversed(T a) {
Reverse(a);
return a;
}
template <class T> inline T Uniqued(T a) {
Unique(a);
return a;
}
template <class T> inline T Uniqed(T a) {
Uniq(a);
return a;
}
template <class T> inline T Rotated(T a, int left) {
Rotate(a, left);
return a;
}
template <class T> inline auto Max(const T& a) {
return *max_element(all(a));
}
template <class T> inline auto Min(const T& a) {
return *min_element(all(a));
}
template <class T> inline int MaxPos(const T& a) {
return max_element(all(a)) - a.begin();
}
template <class T> inline int MinPos(const T& a) {
return min_element(all(a)) - a.begin();
}
template <class T, class F> inline auto MaxBy(const T& a, const F& f) {
return *max_element(all(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
}
template <class T, class F> inline auto MinBy(const T& a, const F& f) {
return *min_element(all(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
}
template <class T, class U> inline int Count(const T& a, const U& v) {
return count(all(a), v);
}
template <class T, class F> inline int CountIf(const T& a, const F& f) {
return count_if(all(a), f);
}
template <class T, class U> inline int Find(const T& a, const U& v) {
return find(all(a), v) - a.begin();
}
template <class T, class F> inline int FindIf(const T& a, const F& f) {
return find_if(all(a), f) - a.begin();
}
template <class T, class U = typename T::value_type> inline U Sum(const T& a) {
return accumulate(all(a), U());
}
template <class T, class U> inline bool Includes(const T& a, const U& v) {
return find(all(a), v) != a.end();
}
template <class T, class F> inline auto Sum(const T& v, const F& f) {
return accumulate(next(v.begin()), v.end(), f(*v.begin()), [&](auto a, auto b) { return a + f(b); });
}
template <class T, class U> inline int Lower(const T& a, const U& v) {
return lower_bound(all(a), v) - a.begin();
}
template <class T, class U> inline int Upper(const T& a, const U& v) {
return upper_bound(all(a), v) - a.begin();
}
template <class T, class F> inline void RemoveIf(T& a, const F& f) {
a.erase(remove_if(all(a), f), a.end());
}
template <class F> inline auto Vector(size_t size, const F& f) {
vector<invoke_result_t<F, size_t>> res(size);
for (size_t i = 0; i < size; ++i) res[i] = f(i);
return res;
}
template <class T> inline auto Grid(size_t h, size_t w, const T& v = T()) {
return vector<vector<T>>(h, vector<T>(w, v));
}
template <class T> inline auto Slice(const T& v, size_t i, size_t len) {
return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
}
template <class T, class F> inline auto Each(const T& v, F&& f) {
for (auto& i : v) f(i);
}
template <class T, class F> inline auto Select(const T& v, const F& f) {
T res;
for (const auto& e : v)
if (f(e)) res.push_back(e);
return res;
}
template <class T, class F> inline auto Map(const T& v, F&& f) {
vector<invoke_result_t<F, typename T::value_type>> res(v.size());
size_t i = 0;
for (const auto& e : v) res[i++] = f(e);
return res;
}
template <class T, class F> inline auto MapIndex(const T& v, const F& f) {
vector<invoke_result_t<F, size_t, typename T::value_type>> res(v.size());
size_t i = 0;
for (auto it = v.begin(); it != v.end(); ++it, ++i) res[i] = f(i, *it);
return res;
}
template <class T, class F> inline auto TrueIndex(const T& v, const F& f) {
vector<size_t> res;
for (size_t i = 0; i < v.size(); ++i)
if (f(v[i])) res.push_back(i);
return res;
}
template <class T, class U = typename T::value_type> inline auto Indexed(const T& v) {
vector<pair<U, int>> res(v.size());
for (int i = 0; i < (int)v.size(); ++i) res[i] = make_pair(static_cast<U>(v[i]), i);
return res;
}
inline auto operator*(string s, size_t n) {
string res;
for (size_t i = 0; i < n; ++i) res += s;
return res;
}
template <class T> inline auto& operator<<(vector<T>& v, const vector<T>& v2) {
v.insert(v.end(), all(v2));
return v;
}
template <class T> inline T Ceil(T n, T m) {
return (n + m - 1) / m;
}
template <class T> inline T Ceil2(T n, T m) {
return Ceil(n, m) * m;
}
template <class T> inline T Tri(T n) {
return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
}
template <class T> inline T nC2(T n) {
return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
}
template <class T> inline T Mid(const T& l, const T& r) {
return l + (r - l) / 2;
}
template <class T> inline bool chmax(T& a, const T& b) {
if (a < b) {
a = b;
return true;
}
return false;
}
template <class T> inline bool chmin(T& a, const T& b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template <class T> inline bool inRange(const T& v, const T& min, const T& max) {
return min <= v && v < max;
}
template <class T> inline bool isSquere(T n) {
T s = sqrt(n);
return s * s == n || (s + 1) * (s + 1) == n;
}
template <class T = long long> inline T BIT(int b) {
return T(1) << b;
}
template <class T, class U = typename T::value_type> inline U Gcdv(const T& v) {
return accumulate(next(v.begin()), v.end(), U(*v.begin()), gcd<U, U>);
}
template <class T, class U = typename T::value_type> inline U Lcmv(const T& v) {
return accumulate(next(v.begin()), v.end(), U(*v.begin()), lcm<U, U>);
}
template <class T> inline T Pow(T a, T n) {
T r = 1;
while (n > 0) {
if (n & 1) r *= a;
a *= a;
n /= 2;
}
return r;
}
template <class T> inline T Powmod(T a, T n, T m = MOD) {
T r = 1;
while (n > 0) {
if (n & 1)
r = r * a % m, n--;
else
a = a * a % m, n /= 2;
}
return r;
}
} // namespace
// --- dump --- //
#if __has_include("/home/yuruhiya/contest/library/dump.hpp")
#include "/home/yuruhiya/contest/library/dump.hpp"
#else
#define dump(...) ((void)0)
#endif
// ---------------------------------------------------------------- //
class BipartiteMatching {
int N, M;
vector<vector<int>> G;
vector<bool> used;
vector<int> p, q;
bool dfs(int v) {
if (used[v]) return false;
used[v] = true;
for (auto u : G[v]) {
if (q[u] == -1 || dfs(q[u])) {
q[u] = v;
p[v] = u;
return true;
}
}
return false;
}
public:
BipartiteMatching(int n, int m, const vector<vector<int>>& g) : N(n), M(m), G(g), used(N), p(N, -1), q(M, -1) {}
BipartiteMatching(int n, int m) : N(n), M(m), G(n), used(N), p(N, -1), q(M, -1) {}
void add_edge(int s, int t) {
G[s].push_back(t);
}
int operator()() {
int res = 0;
bool flag = true;
fill(p.begin(), p.end(), -1);
fill(q.begin(), q.end(), -1);
fill(used.begin(), used.end(), false);
while (flag) {
flag = false;
for (int i = 0; i < N; ++i) {
if (p[i] == -1 && dfs(i)) {
flag = true;
++res;
}
}
if (flag) {
fill(used.begin(), used.end(), false);
}
}
return res;
}
};
struct Point {
static int H, W;
static const vector<Point> d;
static void set_range(int _H, int _W) {
H = _H;
W = _W;
}
static constexpr Point zero() {
return {0, 0};
}
static constexpr Point one() {
return {1, 1};
}
int x, y;
constexpr Point() : x(0), y(0) {}
constexpr Point(int _x, int _y) : x(_x), y(_y) {}
constexpr Point(const pair<int, int>& xy) : x(xy.first), y(xy.second) {}
Point(int n) : x(n % W), y(n / W) {}
constexpr Point operator+() const {
return *this;
}
constexpr Point operator-() const {
return {-x, -y};
}
constexpr Point operator+(const Point& p) const {
return Point(*this) += p;
}
constexpr Point operator-(const Point& p) const {
return Point(*this) -= p;
}
constexpr Point operator*(const Point& p) const {
return Point(*this) *= p;
}
constexpr Point operator/(const Point& p) const {
return Point(*this) /= p;
}
constexpr Point operator%(const Point& p) const {
return Point(*this) %= p;
}
constexpr Point operator+(int n) const {
return Point(*this) += n;
}
constexpr Point operator-(int n) const {
return Point(*this) -= n;
}
constexpr Point operator*(int n) const {
return Point(*this) *= n;
}
constexpr Point operator/(int n) const {
return Point(*this) /= n;
}
constexpr Point operator%(int n) const {
return Point(*this) %= n;
}
constexpr Point& operator+=(const Point& p) {
x += p.x;
y += p.y;
return *this;
}
constexpr Point& operator-=(const Point& p) {
x -= p.x;
y -= p.y;
return *this;
}
constexpr Point& operator*=(const Point& p) {
x *= p.x;
y *= p.y;
return *this;
}
constexpr Point& operator/=(const Point& p) {
x /= p.x;
y /= p.y;
return *this;
}
constexpr Point& operator%=(const Point& p) {
x %= p.x;
y %= p.y;
return *this;
}
constexpr Point& operator+=(int n) {
x += n;
y += n;
return *this;
}
constexpr Point& operator-=(int n) {
x -= n;
y -= n;
return *this;
}
constexpr Point& operator*=(int n) {
x *= n;
y *= n;
return *this;
}
constexpr Point& operator/=(int n) {
x /= n;
y /= n;
return *this;
}
constexpr Point& operator%=(int n) {
x %= n;
y %= n;
return *this;
}
constexpr bool operator==(const Point& p) const {
return x == p.x && y == p.y;
}
constexpr bool operator!=(const Point& p) const {
return x != p.x || y != p.y;
}
bool operator<(const Point& p) const {
return to_i() < p.to_i();
}
bool operator<=(const Point& p) const {
return to_i() <= p.to_i();
}
bool operator>(const Point& p) const {
return to_i() > p.to_i();
}
bool operator>=(const Point& p) const {
return to_i() >= p.to_i();
}
constexpr int operator[](int i) const {
return i == 0 ? x : i == 1 ? y : 0;
}
bool in_range() const {
return 0 <= x && x < W && 0 <= y && y < H;
}
int to_i() const {
return x + y * W;
}
constexpr pair<int, int> to_pair() const {
return {x, y};
}
int dist(const Point& p) const {
return std::abs(x - p.x) + std::abs(y - p.y);
}
int dist_square(const Point& p) const {
return (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y);
}
Point abs(const Point& p) const {
return {std::abs(x - p.x), std::abs(y - p.y)};
}
Point abs() const {
return {std::abs(x), std::abs(y)};
}
Point& swap() {
std::swap(x, y);
return *this;
}
template <class It> vector<Point> enum_adjanect(It first, It last) const {
vector<Point> res;
for (; first != last; ++first) {
res.push_back(operator+(*first));
}
return res;
}
template <class It> vector<Point> enum_adj_in_range(It first, It last) const {
vector<Point> res;
for (; first != last; ++first) {
auto p = operator+(*first);
if (p.in_range()) res.push_back(p);
}
return res;
}
vector<Point> adjacent4() const {
return enum_adjanect(d.begin(), d.begin() + 4);
}
vector<Point> adjacent8() const {
return enum_adjanect(d.begin(), d.end());
}
vector<Point> adj4_in_range() const {
return enum_adj_in_range(d.begin(), d.begin() + 4);
}
vector<Point> adj8_in_range() const {
return enum_adj_in_range(d.begin(), d.end());
}
constexpr Point left() const {
return {x - 1, y};
}
constexpr Point right() const {
return {x + 1, y};
}
constexpr Point up() const {
return {x, y - 1};
}
constexpr Point down() const {
return {x, y + 1};
}
constexpr Point moved(char c) const {
return Point(*this).move(c);
}
constexpr Point& move(char c) {
switch (c) {
case 'L':
case 'l':
case 'W':
case '>': x--; break;
case 'R':
case 'r':
case 'E':
case '<': x++; break;
case 'U':
case 'u':
case 'N':
case '^': y--; break;
case 'D':
case 'd':
case 'S':
case 'v': y++; break;
}
return *this;
}
constexpr Point rotate90() {
return {y, -x};
}
constexpr Point rotate180() {
return {-x, -y};
}
constexpr Point rotate270() {
return {-y, x};
}
friend ostream& operator<<(ostream& os, const Point& p) {
return os << '(' << p.x << ", " << p.y << ')';
}
friend istream& operator>>(istream& is, Point& p) {
return is >> p.x >> p.y;
}
};
int Point::H, Point::W;
const vector<Point> Point::d{{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}};
int main() {
int h = in, w = in;
VS s = in[h];
BipartiteMatching g((h * w + 1) / 2, h * w / 2);
Point::set_range(h, w);
int white = 0, black = 0;
rep(i, h) rep(j, w) {
white += s[i][j] == 'w';
black += s[i][j] == 'b';
if (s[i][j] == 'w') {
for (const auto& p : Point(j, i).adj4_in_range()) {
if (s[p.y][p.x] == 'b') {
g.add_edge(Point(j, i).to_i() / 2, p.to_i() / 2);
}
}
}
}
int res = g();
white -= res;
black -= res;
int ans = res * 100 + min(white, black) * 10 + max(white, black) - min(white, black);
out(ans);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0