Submission #1352906

#TimeUsernameProblemLanguageResultExecution timeMemory
1352906avighnaFish 2 (JOI22_fish2)C++20
100 / 100
874 ms26328 KiB
#include <bits/stdc++.h>

using namespace std;

struct elem {
  int idx, cnt;
  int64_t sum;
  auto operator<=>(const elem &r) const = default;
};

struct node {
  int tl, tr;
  vector<elem> lefts, rights;
  int dominators;
  int64_t sum;
  node() : dominators(0), tl(-1), tr(-1), sum(0) {}
  node(int tl, int tr) : dominators(0), tl(tl), tr(tr), sum(0) {}
  node(int i, int64_t x) : dominators(1), tl(i), tr(i), sum(x) {}
};

class data_structure {
  vector<node> seg;

  int n;
  vector<int64_t> a;

  node merge(const node &left, const node &right) {
    if (left.tl == -1) { return right; }
    if (right.tl == -1) { return left; }

    int tl = left.tl, tr = right.tr, tm = left.tr;
    if (!(tl <= tm && tm <= tr)) {
      return node{};
    }
    node res(tl, tr);
    auto add = [&](int l, int r, int cnt, int64_t sum) {
      if (l != tl && r != tr) { return; }
      if (l == tl && r == tr) {
        res.dominators += cnt;
      } else if (l == tl) {
        res.lefts.push_back({r, cnt, sum});
      } else {
        res.rights.push_back({l, cnt, sum});
      }
    };

    int cur_l = tm, cur_r = tm;
    int64_t sum_l = a[tm], sum_r = 0;
    int ptr_lsuff = left.rights.size() - 1, ptr_rpref = 0;
    auto cur_sum = [&]() { return sum_l + sum_r; };
    auto expand = [&]() {
      auto advance_l = [&]() {
        while (ptr_lsuff >= 0 && left.rights[ptr_lsuff].idx > cur_l) {
          ptr_lsuff--;
        }
        if (ptr_lsuff == -1) {
          cur_l = tl, sum_l = left.sum;
          return;
        }
        cur_l = left.rights[ptr_lsuff].idx, sum_l = left.rights[ptr_lsuff].sum;
      };
      auto advance_r = [&]() {
        while (ptr_rpref < right.lefts.size() && right.lefts[ptr_rpref].idx < cur_r) {
          ptr_rpref++;
        }
        if (ptr_rpref == right.lefts.size()) {
          cur_r = tr, sum_r = right.sum;
          return;
        }
        cur_r = right.lefts[ptr_rpref].idx, sum_r = right.lefts[ptr_rpref].sum;
      };
      int changed = 1;
      while (changed) {
        int _cur_l = cur_l, _cur_r = cur_r;
        changed = 0;
        if (cur_l > tl && cur_sum() >= a[cur_l - 1]) {
          cur_l--;
          advance_l();
        }
        if (cur_r < tr && cur_sum() >= a[cur_r + 1]) {
          cur_r++;
          advance_r();
        }
        changed = _cur_l != cur_l || _cur_r != cur_r;
      }
    };

    // expand left suffixes
    for (int _ = left.rights.size() - 1; _ >= 0; --_) {
      auto [l, cnt, su] = left.rights[_];
      if (l < cur_l) {
        sum_l = su, cur_l = l;
      }
      expand();
      add(cur_l, cur_r, cnt, cur_sum());
    }
    // expand right prefixes
    cur_l = tm + 1, cur_r = tm + 1, sum_l = 0, sum_r = a[tm + 1], ptr_lsuff = left.rights.size() - 1, ptr_rpref = 0;
    for (auto &[r, cnt, su] : right.lefts) {
      if (cur_r < r) {
        sum_r = su, cur_r = r;
      }
      expand();
      add(cur_l, cur_r, cnt, cur_sum());
    }
    // expand left dominators
    cur_l = tl, cur_r = tm, sum_l = left.sum, sum_r = 0, ptr_lsuff = left.rights.size() - 1, ptr_rpref = 0;
    expand();
    add(cur_l, cur_r, left.dominators, cur_sum());
    // expand right dominators
    cur_l = tm + 1, cur_r = tr, sum_l = 0, sum_r = right.sum, ptr_lsuff = left.rights.size() - 1, ptr_rpref = 0;
    expand();
    add(cur_l, cur_r, right.dominators, cur_sum());

    // add left lefts
    for (auto &p : left.lefts) {
      res.lefts.push_back(p);
    }
    // add right rights
    for (auto &p : right.rights) {
      res.rights.push_back(p);
    }

    ranges::sort(res.lefts);
    ranges::sort(res.rights);
    auto dupes = [&](vector<elem> &v) {
      vector<elem> res;
      for (auto &[x, cnt, su] : v) {
        if (!res.empty() && res.back().idx == x) {
          res.back().cnt += cnt;
        } else {
          res.emplace_back(x, cnt, su);
        }
      }
      v = res;
    };
    dupes(res.lefts);
    dupes(res.rights);
    res.sum = left.sum + right.sum;
    return res;
  }

public:
  data_structure(int n, vector<int64_t> a) : a(a), n(n), seg(2 * n) {
    for (int i = 0; i < n; ++i) {
      seg[i + n] = node{i, a[i]};
    }
    for (int i = n - 1; i >= 1; --i) {
      seg[i] = merge(seg[2 * i], seg[2 * i + 1]);
    }
  }

  void set(int i, int x) {
    a[i] = x;
    for (seg[i += n].sum = x, i >>= 1; i > 0; i >>= 1) {
      seg[i] = merge(seg[2 * i], seg[2 * i + 1]);
    }
  }

  int query(int l, int r) {
    node ansL, ansR;
    for (l += n, r += n + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) ansL = merge(ansL, seg[l++]);
      if (r & 1) ansR = merge(seg[--r], ansR);
    }
    return merge(ansL, ansR).dominators;
  }
};

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

  int n;
  cin >> n;
  vector<int64_t> a(n);

  for (int64_t &i : a) {
    cin >> i;
  }

  data_structure ds(n, a);

  int q;
  cin >> q;
  while (q--) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y;
      cin >> x >> y;
      ds.set(x - 1, y);
    } else {
      int l, r;
      cin >> l >> r;
      cout << ds.query(l - 1, r - 1) << '\n';
    }
  }
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...