Submission #1354547

#TimeUsernameProblemLanguageResultExecution timeMemory
1354547avighnaAnts and Sugar (JOI22_sugar)C++20
22 / 100
4072 ms458240 KiB
#include <bits/stdc++.h>

using namespace std;

const int64_t inf = 1e15;

// let stt[N, C, D, CC, CD, DC, DD]
struct state {
private:
  inline static string lookup[7];
  static string idx_to_string(int idx) { return lookup[idx]; }
  static int idx_from_string(const string &s) {
    auto it = find(lookup, lookup + 7, s);
    assert(it != lookup + 7);
    return it - lookup;
  }

public:
  inline static int to[7][7];

  static void init() {
    lookup[0] = "N", lookup[1] = "C", lookup[2] = "D", lookup[3] = "CC", lookup[4] = "CD", lookup[5] = "DC", lookup[6] = "DD";
    for (int i = 0; i < 7; ++i) {
      for (int j = 0; j < 7; ++j) {
        if (i == 0) {
          to[i][j] = j;
        } else if (j == 0) {
          to[i][j] = i;
        } else {
          string comb = idx_to_string(i) + idx_to_string(j);
          if (idx_to_string(i).back() == idx_to_string(j).front()) {
            to[i][j] = -1;
          } else {
            to[i][j] = idx_from_string(string(1, comb.front()) + string(1, comb.back()));
          }
        }
      }
    }
  }

  int64_t stt[7];

  state() { // len>1 identity
    for (int i = 0; i < 7; ++i) { stt[i] = 0; }
  }
  static state get(int64_t len) {
    if (len != 1) {
      return state();
    }
    return state(0, 0);
  }
  state(int64_t c, int64_t d) {
    stt[0] = 0;     // N
    stt[1] = c;     // C
    stt[2] = d;     // D
    stt[3] = -inf;  // CC
    stt[4] = -inf;  // CD
    stt[5] = d + c; // DC
    stt[6] = -inf;  // DD
  }

  static state idt() {
    state res;
    for (int i = 0; i < 7; ++i) { res.stt[i] = -inf; }
    return res;
  }
  bool operator==(const state &r) const = default;
};

state operator+(const state &l, const state &r) {
  if (l == state::idt()) {
    return r;
  }
  if (r == state::idt()) {
    return l;
  }
  state res = state::idt();
  for (int i = 0; i < 7; ++i) {
    for (int j = 0; j < 7; ++j) {
      int which = state::to[i][j];
      if (which != -1) {
        res.stt[which] = max(res.stt[which], l.stt[i] + r.stt[j]);
      }
    }
  }
  return res;
}

template <typename T>
class sparse_segment_tree {
  struct node {
    T cur;
    int64_t lazy, lazy_c;
    node *l, *r;
    node(int64_t len) : l(nullptr), r(nullptr), lazy(0), lazy_c(0) {
      if constexpr (is_same_v<T, state>) {
        cur = T::get(len);
      } else {
        cur = T{};
      }
    }
    ~node() {
      delete l;
      delete r;
    }
  };

  int64_t tl, tr;
  node *t;

  void push(node *t, int64_t tl, int64_t tr) {
    // [N, C, D, CC, CD, DC, DD]
    if constexpr (is_same_v<T, state>) {
      static constexpr array<int, 7> m = {0, 1, -1, 1, 0, 0, -1};
      static constexpr std::array<int, 7> m_c = {0, 1, 0, 2, 1, 1, 1};
      for (int i = 0; i < 7; ++i) {
        t->cur.stt[i] += m[i] * t->lazy;
        t->cur.stt[i] += m_c[i] * t->lazy_c;
      }
      if (tl == tr) {
        t->lazy = 0, t->lazy_c = 0;
        return;
      }
      int64_t tm = midpoint(tl, tr);
      t->l = t->l ? t->l : new node(tm - tl + 1);
      t->r = t->r ? t->r : new node(tr - tm);
      t->l->lazy += t->lazy, t->l->lazy_c += t->lazy_c;
      t->r->lazy += t->lazy, t->r->lazy_c += t->lazy_c;
      t->lazy = 0, t->lazy_c = 0;
    }
  }

  void pull(node *t) {
    t->cur = t->l->cur + t->r->cur;
  }

  void set(node *t, int64_t tl, int64_t tr, int64_t i, T st) {
    push(t, tl, tr);
    if (tr < i || i < tl) {
      return;
    }
    if (tl == tr && tl == i) {
      t->cur = st;
      return;
    }
    int64_t tm = midpoint(tl, tr);
    t->l = t->l ? t->l : new node(tm - tl + 1);
    t->r = t->r ? t->r : new node(tr - tm);
    set(t->l, tl, tm, i, st);
    set(t->r, tm + 1, tr, i, st);
    pull(t);
  }

  T query(node *t, int64_t tl, int64_t tr, int64_t l, int64_t r) {
    push(t, tl, tr);
    if (tr < l || r < tl) {
      if constexpr (is_same_v<T, state>) {
        return T::idt();
      } else {
        return T{};
      }
    }
    if (l <= tl && tr <= r) {
      return t->cur;
    }
    int64_t tm = midpoint(tl, tr);
    t->l = t->l ? t->l : new node(tm - tl + 1);
    t->r = t->r ? t->r : new node(tr - tm);
    T res = query(t->l, tl, tm, l, r) + query(t->r, tm + 1, tr, l, r);
    pull(t);
    return res;
  }

  void add_same_suffix(node *t, int64_t tl, int64_t tr, int64_t l, int64_t x)
    requires is_same_v<T, state>
  {
    push(t, tl, tr);
    if (tr < l) {
      return;
    }
    if (l <= tl) {
      t->lazy += x;
      push(t, tl, tr);
      return;
    }
    int64_t tm = midpoint(tl, tr);
    t->l = t->l ? t->l : new node(tm - tl + 1);
    t->r = t->r ? t->r : new node(tr - tm);
    add_same_suffix(t->l, tl, tm, l, x);
    add_same_suffix(t->r, tm + 1, tr, l, x);
    pull(t);
  }

  void add_range_c(node *t, int64_t tl, int64_t tr, int64_t l, int64_t r, int64_t x)
    requires is_same_v<T, state>
  {
    push(t, tl, tr);
    if (tr < l || r < tl) {
      return;
    }
    if (l <= tl && tr <= r) {
      t->lazy_c += x;
      push(t, tl, tr);
      return;
    }
    int64_t tm = midpoint(tl, tr);
    t->l = t->l ? t->l : new node(tm - tl + 1);
    t->r = t->r ? t->r : new node(tr - tm);
    add_range_c(t->l, tl, tm, l, r, x);
    add_range_c(t->r, tm + 1, tr, l, r, x);
    pull(t);
  }

public:
  sparse_segment_tree(int64_t tl, int64_t tr) : tl(tl), tr(tr), t(new node(tr - tl + 1)) {}
  ~sparse_segment_tree() { delete t; }

  void set(int64_t i, T st) { set(t, tl, tr, i, st); }
  T query(int64_t l, int64_t r) { return query(t, tl, tr, l, r); }
  void add_same_suffix(int64_t l, int64_t x)
    requires is_same_v<T, state>
  {
    add_same_suffix(t, tl, tr, l, x);
  }
  void add_range_c(int64_t l, int64_t r, int64_t x)
    requires is_same_v<T, state>
  {
    add_range_c(t, tl, tr, l, r, x);
  }
};

struct query {
  int t, x, v;
};

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  state::init();

  vector<int64_t> buff;

  int q, L;
  cin >> q >> L;
  vector<query> queries(q);
  for (auto &[t, x, v] : queries) {
    cin >> t >> x >> v;
    buff.push_back(x);
    buff.push_back(x + 1);
    buff.push_back(x + L + 1);
    buff.push_back(x - L);
    buff.push_back(x + L);
  }

  int64_t lo = -1e9 - 10, hi = 2e9 + 10;
  buff.push_back(lo + L + 1), buff.push_back(hi - L);

  sort(buff.begin(), buff.end());
  buff.erase(unique(buff.begin(), buff.end()), buff.end());
  auto C = [&](int64_t x) { return lower_bound(buff.begin(), buff.end(), x) - buff.begin(); };

  sparse_segment_tree<state> st(C(lo + L + 1), C(hi - L));

  auto compute = [&]() {
    return st.query(C(lo + L + 1), C(hi - L)).stt[5];
  };

  int64_t sum_ants = 0;
  auto add_ants = [&](int x, int v) {
    sum_ants += v;
    st.add_range_c(C(x), C(x), v);
    st.add_same_suffix(C(x + 1), v);
  };

  auto add_sugar = [&](int x, int v) {
    st.add_same_suffix(C(x + L + 1), -v);
    st.add_range_c(C(x - L), C(x + L), -v);
  };

  for (auto &[t, x, v] : queries) {
    if (t == 1) {
      add_ants(x, v);
    } else {
      add_sugar(x, v);
    }
    cout << min(sum_ants, sum_ants - compute()) << '\n';
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...