Submission #17327401


Source Code Expand

#include <bits/stdc++.h>
using namespace std;

// 0-indexed
template <class T>
struct SegmentTree {
  // a,b,c: T, e:T(unit)
  // abc = (ab)c = a(bc)
  // ae = ea = a
  typedef function<T(T, T)> F;
  int n;
  F f;
  T unit;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int newn, F f, T t) : f(f), unit(t) { init(newn); }
  SegmentTree(const vector<T> &v, F f, T t) : f(f), unit(t) {
    int _n = v.size();
    init(v.size());
    for (int i = 0; i < _n; ++i) dat[n + i] = v[i];
    for (int i = n - 1; i; --i) dat[i] = f(dat[i << 1], dat[(i << 1) | 1]);
  }
  void init(int newn) {
    n = 1;
    while (n < newn) n <<= 1;
    dat.assign(n << 1, unit);
  }

  // "go up" process
  void update(int k, T newdata) {
    dat[k += n] = newdata;
    while (k >>= 1) {
      dat[k] = f(dat[(k << 1) | 0], dat[(k << 1) | 1]);
    }
  }
  // [a,b)
  T query(int a, int b) {
    T vl = unit, vr = unit;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) vl = f(vl, dat[l++]);
      if (r & 1) vr = f(dat[--r], vr);
    }
    return f(vl, vr);
  }
  // func(unit) == false
  // min left: st <= res && func(seg.query(res,n))
  template <typename C>
  int find_left(int st, C &func, T acc, int k, int l, int r) {
    if (l + 1 == r) {
      acc = f(acc, dat[k]);
      return func(acc) ? l : -1;
    }
    int mid = (l + r) >> 1;
    if (mid <= st) return find_left(st, func, acc, (k << 1) | 1, mid, r);
    if (st <= l && !func(f(acc, dat[k]))) {
      acc = f(acc, dat[k]);
      return -1;
    }
    int nres = find_left(st, func, acc, (k << 1), l, mid);
    if (~nres) return nres;
    return find_left(st, func, acc, (k << 1) | 1, mid, r);
  }
  template <typename C>
  int find_left(int st, C &func) {
    T acc = unit;
    return find_left(st, func, acc, 1, 0, n);
  }

  // max right: res <= st && func(seg.query(0,res))
  template <typename C>
  int find_right(int st, C &func, T acc, int k, int l, int r) {
    if (l + 1 == r) {
      acc = f(dat[k], acc);
      return func(acc) ? r : -1;
    }
    int mid = (l + r) >> 1;
    if (st <= mid) return find_right(st, func, acc, k << 1, l, mid);
    if (r <= st && !func(f(dat[k], acc))) {
      acc = f(dat[k], acc);
      return -1;
    }
    int nres = find_right(st, func, acc, (k << 1) | 1, mid, r);
    if (~nres) return nres;
    return find_right(st, func, acc, k << 1, l, mid);
  }
  template <typename C>
  int find_right(int st, C &func) {
    T acc = unit;
    return find_right(st, func, acc, 1, 0, n);
  }
};

struct dat {
  array<int, 5> num;
  dat() { iota(num.begin(), num.end(), 0); }
};

int h, w;
vector<pair<int, int>> beans;
vector<string> s, rs;
vector<vector<int>> grundy, rgrundy;

int solve();

int main() {
  cin >> h >> w;
  s.resize(h);
  rs.resize(h);
  for (int i = 0; i < h; ++i) {
    cin >> s[i];
    for (int j = 0; j < w; ++j)
      if (s[i][j] == 'B') {
        beans.emplace_back(i, j);
        s[i][j] = '.';
      }
    rs[i] = s[i];
    reverse(rs[i].begin(), rs[i].end());
  }
  if (solve())
    cout << "Alice" << endl;
  else
    cout << "Bob" << endl;
  return 0;
}

int solve() {
  int res = 0;
  grundy.assign(h + 1, vector<int>(w, 4));
  rgrundy = grundy;
  auto make_seg = [](const string &str, const vector<int> &g) {
    auto f = [](dat l, dat r) {
      dat res;
      for (int j = 0; j < 5; ++j) res.num[j] = r.num[l.num[j]];
      return res;
    };
    SegmentTree<dat> seg(2 * w, f, dat());
    for (int j = 0; j < 2 * w; ++j) {
      dat now;
      vector<int> cnt(5, 0);
      ++cnt[g[j % w]];
      for (int k = 0; k < 5; ++k) {
        if (str[j % w] == '#')
          now.num[k] = 4;
        else {
          ++cnt[k];
          for (int p = 0; p < 5; ++p)
            if (!cnt[p]) {
              now.num[k] = p;
              break;
            }
          --cnt[k];
        }
      }
      seg.update(j, now);
    }
    return seg;
  };
  for (int i = h - 1; i >= 0; --i) {
    SegmentTree<dat> segl, segr;
    segl = make_seg(s[i], grundy[i + 1]);
    segr = make_seg(rs[i], rgrundy[i + 1]);
    for (int j = 0; j < w; ++j)
      if (s[i][j] == '.') {
        vector<int> cnt(5, 0);
        ++cnt[grundy[i + 1][j]];
        ++cnt[segl.query(j + 1, j + w).num[4]];
        ++cnt[segr.query(w - j, 2 * w - 1 - j).num[4]];
        for (int p = 0; p < 5; ++p)
          if (!cnt[p]) {
            grundy[i][j] = p;
            break;
          }
      }
    rgrundy[i] = grundy[i];
    reverse(rgrundy[i].begin(), rgrundy[i].end());
  }
  for (auto [x, y] : beans) res ^= grundy[x][y];
  return res;
}

Submission Info

Submission Time
Task H - Beans on the Grid
User m_tsubasa
Language C++ (GCC 9.2.1)
Score 300
Code Size 4717 Byte
Status AC
Exec Time 1016 ms
Memory 21144 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 300 / 300
Status
AC × 4
AC × 45
Set Name Test Cases
Sample 00_sample_00, 00_sample_01, 00_sample_02, 00_sample_03
All 00_sample_00, 00_sample_01, 00_sample_02, 00_sample_03, 01_small_0, 01_small_1, 01_small_2, 01_smallloops_0, 01_smallloops_1, 01_smallloops_2, 01_smallw1_0, 01_smallw1_1, 01_smallw1_2, 01_toosmall_0, 01_toosmall_1, 01_toosmall_2, 02_large_0, 02_large_1, 02_large_2, 02_largeloops_0, 02_largeloops_1, 02_largeloops_2, 02_largew1_0, 02_largew1_1, 02_largew1_2, 03_almostb_0, 03_almostb_1, 03_almostb_2, 03_almostb_3, 03_almostb_4, 03_anti_edagari_0, 03_anti_edagari_1, 03_anti_edagari_2, 03_anti_edagari_3, 03_anti_edagari_4, 03_anti_edagari_5, 03_anti_edagari_6, 03_anti_edagari_7, 03_anti_edagari_8, 03_anti_edagari_9, 03_nowall_0, 03_nowall_1, 03_nowall_2, 03_nowall_3, 03_nowall_4
Case Name Status Exec Time Memory
00_sample_00 AC 10 ms 3616 KiB
00_sample_01 AC 2 ms 3584 KiB
00_sample_02 AC 2 ms 3560 KiB
00_sample_03 AC 2 ms 3488 KiB
01_small_0 AC 69 ms 4476 KiB
01_small_1 AC 11 ms 3492 KiB
01_small_2 AC 5 ms 3612 KiB
01_smallloops_0 AC 9 ms 3668 KiB
01_smallloops_1 AC 61 ms 4244 KiB
01_smallloops_2 AC 34 ms 3928 KiB
01_smallw1_0 AC 8 ms 3564 KiB
01_smallw1_1 AC 2 ms 3564 KiB
01_smallw1_2 AC 2 ms 3504 KiB
01_toosmall_0 AC 2 ms 3476 KiB
01_toosmall_1 AC 2 ms 3636 KiB
01_toosmall_2 AC 3 ms 3592 KiB
02_large_0 AC 396 ms 9740 KiB
02_large_1 AC 666 ms 14296 KiB
02_large_2 AC 62 ms 4180 KiB
02_largeloops_0 AC 8 ms 3692 KiB
02_largeloops_1 AC 119 ms 5068 KiB
02_largeloops_2 AC 247 ms 7032 KiB
02_largew1_0 AC 9 ms 3704 KiB
02_largew1_1 AC 5 ms 3632 KiB
02_largew1_2 AC 2 ms 3628 KiB
03_almostb_0 AC 985 ms 21064 KiB
03_almostb_1 AC 979 ms 20760 KiB
03_almostb_2 AC 968 ms 20532 KiB
03_almostb_3 AC 965 ms 20512 KiB
03_almostb_4 AC 968 ms 20716 KiB
03_anti_edagari_0 AC 989 ms 20940 KiB
03_anti_edagari_1 AC 1007 ms 21052 KiB
03_anti_edagari_2 AC 978 ms 21004 KiB
03_anti_edagari_3 AC 990 ms 21016 KiB
03_anti_edagari_4 AC 1016 ms 20932 KiB
03_anti_edagari_5 AC 984 ms 21144 KiB
03_anti_edagari_6 AC 1012 ms 20992 KiB
03_anti_edagari_7 AC 989 ms 20744 KiB
03_anti_edagari_8 AC 1010 ms 21000 KiB
03_anti_edagari_9 AC 1012 ms 21056 KiB
03_nowall_0 AC 932 ms 19012 KiB
03_nowall_1 AC 959 ms 19204 KiB
03_nowall_2 AC 953 ms 19272 KiB
03_nowall_3 AC 947 ms 19048 KiB
03_nowall_4 AC 933 ms 18940 KiB