제출 #1348900

#제출 시각아이디문제언어결과실행 시간메모리
1348900avighnaTeam Contest (JOI22_team)C++20
100 / 100
946 ms72848 KiB
#include <bits/stdc++.h>

using namespace std;

struct triplet {
  int x, y, z;
  triplet() : x(0), y(0), z(0) {}
  auto operator<=>(const triplet &r) const = default;
};

const int inf = 5e8;

class lazy_segment_tree {
  int n;
  vector<int> seg, lazy;

  void push(int v) {
    seg[v] += lazy[v];
    lazy[2 * v] += lazy[v];
    lazy[2 * v + 1] += lazy[v];
    lazy[v] = 0;
  }
  void pull(int v) { seg[v] = max(seg[2 * v], seg[2 * v + 1]); }
  void add(int v, int tl, int tr, int l, int r, int del) {
    push(v);
    if (tr < l || r < tl) {
      return;
    }
    if (l <= tl && tr <= r) {
      lazy[v] += del;
      push(v);
      return;
    }
    int tm = (tl + tr) / 2;
    add(2 * v, tl, tm, l, r, del);
    add(2 * v + 1, tm + 1, tr, l, r, del);
    pull(v);
  }
  int query(int v, int tl, int tr, int l, int r) {
    push(v);
    if (tr < l || r < tl) {
      return -inf;
    }
    if (l <= tl && tr <= r) {
      return seg[v];
    }
    int tm = (tl + tr) / 2;
    return max(query(2 * v, tl, tm, l, r), query(2 * v + 1, tm + 1, tr, l, r));
  }
  template <typename Fn>
  int min_right(int v, int tl, int tr, int l, const Fn &f) {
    push(v);
    if (!f(seg[v]) || tr < l) {
      return n;
    }
    if (tl == tr) {
      return tl;
    }
    int tm = (tl + tr) / 2;
    int ans = min_right(2 * v, tl, tm, l, f);
    if (ans != n) {
      return ans;
    }
    return min_right(2 * v + 1, tm + 1, tr, l, f);
  }

public:
  lazy_segment_tree(int n) : n(n), seg(4 * n), lazy(8 * n) {}

  void add(int l, int r, int del) { add(1, 0, n - 1, l, r, del); }
  int query(int l, int r) { return query(1, 0, n - 1, l, r); }
  template <typename Fn>
  int min_right(int l, const Fn &f) { return min_right(1, 0, n - 1, l, f); }
};

struct point {
  int y, z;
};

class data_structure {
  vector<int> buff;
  vector<int> at_y;
  lazy_segment_tree pref_max;
  lazy_segment_tree opt;
  lazy_segment_tree activate;

  int compr(int x) { return lower_bound(buff.begin(), buff.end(), x) - buff.begin(); }

  bool is_active(int y) {
    return pref_max.query(y, y) - at_y[y] > 0;
  }

  void incr_range(int l, int r, int del) {
    pref_max.add(l, r, del);
    activate.add(l, r, del);
    opt.add(l, r, del);
  }

  void chmax(int i, int x) { // st[i] = max(st[i], x)
    int old = pref_max.query(i, i);
    if (x <= old) {
      return;
    }
    // we may need to update pref_max[i/i+1/i+2/...]
    for (int l = i, r; l < buff.size() + 1; l = r) {
      int val = pref_max.query(l, l);
      r = pref_max.min_right(l, [&](int x) { return x > val; });
      if (x - val <= 0) {
        break;
      }
      incr_range(l, r - 1, x - val);
    }
  }

  void activate_vals() {
    auto fn = [&](int x) { return x > 0; };
    for (int i = activate.min_right(0, fn); i != buff.size() + 1; i = activate.min_right(0, fn)) {
      opt.add(i, i, inf);       // undo -inf deactivated buff, activate
      activate.add(i, i, -inf); // an already active value won't be activated again
    }
  }

public:
  data_structure(const vector<int> &buff) : buff(buff), at_y(buff.size(), inf), pref_max(buff.size() + 1), opt(buff.size() + 1), activate(buff.size() + 1) {
    pref_max.add(0, buff.size(), -inf);
    for (int i = 0; i <= buff.size(); ++i) {
      opt.add(i, i, (i < buff.size() ? buff[i] : 0) + (-inf) - inf); // buff[i] + st.query(0, i), and -inf because deactivated
      activate.add(i, i, (-inf) - at_y[i]);
    }
  }

  void add(int y, int z) {
    y = compr(y);
    activate.add(y, y, at_y[y]);
    at_y[y] = min(at_y[y], z);
    activate.add(y, y, -at_y[y]);
    chmax(y + 1, z);
    activate_vals();
  }

  int query(int Y, int Z) {
    int ans = -inf;
    int y = max(pref_max.min_right(0, [&](int x) { return x > Z; }), compr(Y + 1));
    if (y > buff.size() - 1) {
      return ans;
    }
    return max(ans, opt.query(y, buff.size() - 1));
  }
};

int solve(int n, vector<triplet> a) {
  vector<int> buff;
  for (auto &[x, y, z] : a) {
    buff.push_back(y), buff.push_back(y - 1), buff.push_back(y + 1);
  }
  sort(buff.begin(), buff.end());
  buff.erase(unique(buff.begin(), buff.end()), buff.end());

  data_structure ds(buff);
  int ans = -1;
  for (int i = 0, j = 0; i < n; ++i) {
    while (j < i && a[j].x < a[i].x) {
      ds.add(a[j].y, a[j].z);
      j++;
    }
    ans = max(ans, a[i].x + ds.query(a[i].y, a[i].z));
  }

  return ans;
}

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

  int n;
  cin >> n;
  vector<triplet> a(n);
  for (auto &[x, y, z] : a) {
    cin >> x >> y >> z;
  }
  sort(a.begin(), a.end());
  a.erase(unique(a.begin(), a.end()), a.end());
  n = a.size();

  int ans = solve(n, a);
  for (auto &[x, y, z] : a) {
    swap(y, z);
  }
  cout << max(ans, solve(n, a)) << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...