제출 #632641

#제출 시각아이디문제언어결과실행 시간메모리
632641evenvalueMeetings (IOI18_meetings)C++17
0 / 100
415 ms15888 KiB
#include "meetings.h"
#include <bits/stdc++.h>
using namespace std;

template<typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
template<typename T>
using max_heap = priority_queue<T, vector<T>, less<T>>;

using int64 = long long;
using ld = long double;

constexpr int kInf = 1e9 + 10;
constexpr int64 kInf64 = 1e18 + 10;
constexpr int kMod = 1e9 + 7;
constexpr int kMaxHeight = 23;

template<class node, class F = std::function<node(const node &, const node &)>>
class SegTree {
  int n = 0;
  std::vector<node> t;
  F unite;

  void build(const int x, const int l, const int r, const std::vector<node> &a) {
    if (l == r) {
      t[x] = a[l];
      return;
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    build(x + 1, l, mid, a);
    build(y, mid + 1, r, a);
    t[x] = unite(t[x + 1], t[y]);
  }

  void update(const int x, const int l, const int r, const int p, const node &v) {
    if (l == p and p == r) {
      t[x] = v;
      return;
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    if (p <= mid) {
      update(x + 1, l, mid, p, v);
    } else {
      update(y, mid + 1, r, p, v);
    }
    t[x] = unite(t[x + 1], t[y]);
  }

  node query(const int x, const int l, const int r, const int ql, const int qr) const {
    if (ql <= l and r <= qr) {
      return t[x];
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    if (qr <= mid) {
      return query(x + 1, l, mid, ql, qr);
    } else if (mid < ql) {
      return query(y, mid + 1, r, ql, qr);
    } else {
      return unite(query(x + 1, l, mid, ql, qr), query(y, mid + 1, r, ql, qr));
    }
  }

  void debug_node(const int x, const vector<int> &path) const {
    for (int i = 0; i < path.size(); i++) {
      cerr << path[i] << (i == path.size() - 1 ? ": " : " -> ");
    }
    cerr << t[x] << '\n';
  }

  void debug(const int x, const int l, const int r, vector<int> path) const {
    path.push_back(x);
    if (l == r) {
      debug_node(x, path);
      return;
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    debug(x + 1, l, mid, path);
    debug(y, mid + 1, r, path);
    debug_node(x, path);
  }

public:
  SegTree() = default;
  explicit SegTree(const int n, const node e, F f) : n(n), t(2 * n - 1, e), unite(std::move(f)) {}
  explicit SegTree(const std::vector<node> &a, F f) : n(a.size()), t(2 * (a.size()) - 1), unite(std::move(f)) {
    build(0, 0, n - 1, a);
  }

  void set(const int p, const node &v) {
    assert(0 <= p and p < n);
    update(0, 0, n - 1, p, v);
  }

  [[nodiscard]] node get(const int l, const int r) const {
    assert(0 <= l and l <= r and r < n);
    return query(0, 0, n - 1, l, r);
  }

  void debug() const {
    debug(0, 0, n - 1, {});
    cerr << "----------\n\n";
  }
};

struct node {
  int peak;
  vector<int64> left;
  vector<int64> right;
  vector<int64> costl;
  vector<int64> costr;

  explicit node(const int n, const int peak = kMaxHeight - 1) : peak(peak), left(n), right(n),
                                                                costl(n, kInf64), costr(n, kInf64) {}
};

std::vector<long long> minimum_costs(std::vector<int> H, std::vector<int> L, std::vector<int> R) {
  H.push_back(1);
  const int n = (int) H.size(), q = (int) L.size();

  SegTree<node> st(n, node(kMaxHeight), [](const node &l, const node &r) {
    node ret(kMaxHeight, max(l.peak, r.peak));
    //ret.left
    ret.left = l.left;
    ret.left[l.peak] += accumulate(r.left.begin(), r.left.begin() + l.peak + 1, 0LL);
    for (int i = l.peak + 1; i < kMaxHeight; i++) {
      ret.left[i] += r.left[i];
    }
    //ret.right
    ret.right = r.right;
    ret.right[r.peak] += accumulate(l.right.begin(), l.right.begin() + r.peak + 1, 0LL);
    for (int i = r.peak + 1; i < kMaxHeight; i++) {
      ret.right[i] += l.right[i];
    }
    //ret.costl
    int64 sum = 0;
    int64 sum2 = 0;
    for (int i = 1; i < kMaxHeight; i++) {
      sum2 += r.left[i] * i;
    }
    for (int hR = 1; hR < kMaxHeight; hR++) {
      sum += r.left[hR];
      sum2 -= r.left[hR] * hR;
      const int new_hR = max(hR, r.peak);
      ret.costl[new_hR] = min(ret.costl[new_hR], l.costl[hR] + (sum * hR) + sum2);
      if (new_hR == ret.peak) {
        ret.costr[ret.peak] = min(ret.costr[ret.peak], l.costl[hR] + (sum * hR) + sum2);
      }
    }
    //ret.costr
    sum = 0;
    sum2 = 0;
    for (int i = 1; i < kMaxHeight; i++) {
      sum2 += l.right[i] * i;
    }
    for (int hL = 1; hL < kMaxHeight; hL++) {
      sum += l.right[hL];
      sum2 -= l.right[hL] * hL;
      const int new_hL = max(hL, l.peak);
      ret.costr[new_hL] = min(ret.costr[new_hL], r.costr[hL] + (sum * hL) + sum2);
      if (new_hL == ret.peak) {
        ret.costl[ret.peak] = min(ret.costl[ret.peak], r.costr[hL] + (sum * hL) + sum2);
      }
    }
    return ret;
  });

  assert(st.get(0, n - 1).peak < kMaxHeight);

  for (int i = 0; i < n; i++) {
    node x(kMaxHeight, H[i]);
    x.left[H[i]] = 1;
    x.right[H[i]] = 1;
    fill(x.costl.begin(), x.costl.end(), H[i]);
    fill(x.costr.begin(), x.costr.end(), H[i]);
    st.set(i, x);
  }

  vector<int64> ans(q);
  for (int i = 0; i < q; i++) {
    const node x = st.get(L[i], R[i]);
    ans[i] = min(*min_element(x.costl.begin(), x.costl.end()),
                 *min_element(x.costr.begin(), x.costr.end()));
  }
  return ans;
}
#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...