Submission #993605

#TimeUsernameProblemLanguageResultExecution timeMemory
993605poqmenMeetings (IOI18_meetings)C++14
100 / 100
2508 ms487248 KiB
#include "meetings.h"

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

// x -> a * x + b
const int64_t OFFSET_SENTINEL = INT64_MIN + 1557;
struct LinearMap {
  int64_t a;
  int64_t b;
  LinearMap operator()(const LinearMap& rhs) {
    if (a == OFFSET_SENTINEL) return {rhs.a, rhs.b + b};
    return *this;
  }
  int64_t operator()(const int64_t rhs) { return a * rhs + b; }
};

struct SegTree {
  // if lazy.a == OFFSET_SENTINEL: x -> x+lazy.b
  // else x -> lazy.a * i + lazy.b
  vector<LinearMap> lazy;
  // seg holds leftmost val;
  vector<LinearMap> seg;
  int n;
  void _build(int node, int l, int r, vector<int>& src) {
    seg[node] = {0, src[l]};
    int m = (l + r) / 2;
    _build(2 * node + 1, l, m, src);
    _build(2 * node + 2, m, r, src);
  }
  void build(vector<int>& src) {
    n = src.size();
    lazy.assign(4 * n, {OFFSET_SENTINEL, 0});
    seg.assign(4 * n, {0, 0});
  }
  void propagate(int node, int l, int r) {
    if (l + 1 == r) return;
    seg[2 * node + 1] = lazy[node](seg[2 * node + 1]);
    lazy[2 * node + 1] = lazy[node](lazy[2 * node + 1]);
    seg[2 * node + 2] = lazy[node](seg[2 * node + 2]);
    lazy[2 * node + 2] = lazy[node](lazy[2 * node + 2]);
    lazy[node] = {OFFSET_SENTINEL, 0};
  }
  void _apply_range(int node, int l, int r, int ql, int qr, LinearMap& f) {
    if (ql <= l && r <= qr) {
      lazy[node] = f(lazy[node]);
      seg[node] = f(seg[node]);
      return;
    }
    if (qr <= l || r <= ql) return;
    propagate(node, l, r);
    int m = (l + r) / 2;
    _apply_range(2 * node + 1, l, m, ql, qr, f);
    _apply_range(2 * node + 2, m, r, ql, qr, f);
    seg[node] = seg[2 * node + 1];
  }
  void apply_range(int l, int r, LinearMap f) {
    _apply_range(0, 0, n, l, r, f);
  }
  int _search_left(int node, int l, int r, int ql, int qr, LinearMap& f) {
    propagate(node, l, r);
    if (l + 1 == r) {
      if (f(l) < seg[node](l)) return l;
      return r;
    }

    int m = (l + r) / 2;
    if (ql <= m && m < qr) {
      LinearMap fm = seg[2 * node + 2];
      if (f(m) < fm(m)) {
        return _search_left(2 * node + 1, l, m, ql, qr, f);
      } else {
        return _search_left(2 * node + 2, m, r, ql, qr, f);
      }
    } else if (m < ql) {
      return _search_left(2 * node + 2, m, r, ql, qr, f);
    } else {
      return _search_left(2 * node + 1, l, m, ql, qr, f);
    }
  }
  int _search_right(int node, int l, int r, int ql, int qr, LinearMap& f) {
    propagate(node, l, r);
    if (l + 1 == r) {
      if (f(l) < seg[node](l)) return l;
      return l - 1;
    }

    int m = (l + r) / 2;
    if (ql <= m && m < qr) {
      LinearMap fm = seg[2 * node + 2];
      if (f(m) < fm(m)) {
        return _search_right(2 * node + 2, m, r, ql, qr, f);
      } else {
        return _search_right(2 * node + 1, l, m, ql, qr, f);
      }
    } else if (m < ql) {
      return _search_right(2 * node + 2, m, r, ql, qr, f);
    } else {
      return _search_right(2 * node + 1, l, m, ql, qr, f);
    }
  }
  // smallest i s.t. LinearMap(i) < seg[i]
  int search_left(int l, int r, LinearMap f) {
    return _search_left(0, 0, n, l, r, f);
  }
  // biggest i s.t. LinearMap(i) < seg[i]
  int search_right(int l, int r, LinearMap f) {
    return _search_right(0, 0, n, l, r, f);
  }
  int64_t _value(int node, int l, int r, int i) {
    propagate(node, l, r);
    if (l == i) return seg[node](i);
    int m = (l + r) / 2;
    if (i >= m)
      return _value(2 * node + 2, m, r, i);
    else
      return _value(2 * node + 1, l, m, i);
  }
  int64_t value(int i) {
    if (i == n) {
      cout << "FAIL\n";
    }
    return _value(0, 0, n, i);
  }
};

struct RMQ {
  vector<vector<int>> sparse;
  vector<int>* src;
  void build(vector<int>* _src) {
    src = _src;
    sparse.emplace_back(src->size(), 0);
    for (int i = 0; i < src->size(); ++i) {
      sparse[0][i] = i;
    }
    for (int i = 2, li = 1; i < 2 * src->size(); i = 2 * i, li += 1) {
      sparse.emplace_back(src->size(), 0);
      for (int j = 0; j + i <= src->size(); ++j) {
        int lidx = sparse[li - 1][j];
        int ridx = sparse[li - 1][j + i / 2];
        sparse[li][j] = (*src)[lidx] < (*src)[ridx] ? ridx : lidx;
      }
    }
  }
  int rmq(int l, int r) {
    int k = __lg(r - l);
    int lidx = sparse[k][l];
    int ridx = sparse[k][r - (1 << k)];
    return (*src)[lidx] < (*src)[ridx] ? ridx : lidx;
  }
};

vector<long long> minimum_costs(vector<int> h, vector<int> ql, vector<int> qr) {
  int n = h.size(), q = ql.size();
  vector<long long> ans(q);
  vector<vector<int>> assigned_queries(n);
  // dp_left: r fixed, dp_right: l fixed
  SegTree dp_left, dp_right;
  dp_left.build(h), dp_right.build(h);
  RMQ rmq;
  rmq.build(&h);
  for (int i = 0; i < q; ++i) {
    qr[i] += 1;
    assigned_queries[rmq.rmq(ql[i], qr[i])].push_back(i);
  }
  function<void(int, int)> traverse = [&](int l, int r) {
    if (l >= r) return;
    int64_t m = rmq.rmq(l, r);
    traverse(l, m);
    traverse(m + 1, r);
    for (auto q : assigned_queries[m]) {
      int cl = ql[q], cr = qr[q];
      int64_t lmax = cl == m ? 0 : dp_left.value(cl);
      int64_t rmax = cr - 1 == m ? 0 : dp_right.value(cr - 1);
      ans[q] = min(lmax + h[m] * (cr - m), rmax + h[m] * (m - cl + 1));
    }
    // merge dp_left and dp_right
    // dp_left[l..]
    // dp_left[l..=m] = min(dp_left[l..=m] + h[m] * (r - m), dp_left[m + 1] +
    // (m
    // - i + 1) * h[m])
    int64_t value_r = m == r - 1 ? 0 : dp_left.value(m + 1);
    int64_t value_l = m == l ? 0 : dp_right.value(m - 1);
    if (m == r - 1) {
      // if (l == 0 && r == 4) {
      //   int x = 3;
      // }
      dp_left.apply_range(l, m, {OFFSET_SENTINEL, h[m]});
      dp_left.apply_range(m, m + 1, {0, h[m]});
    } else {
      // if (l == 1 && r == 4) {
      //   int x = 3;
      // }
      dp_left.apply_range(m, m + 1, {0, value_r + h[m]});
      // cout << "dpl: ";
      // for (int i = 0; i < n; ++i) {
      //   cout << dp_left.value(i) << " ";
      // }
      // cout << "\n";
      dp_left.apply_range(l, m, {OFFSET_SENTINEL, h[m] * (r - m)});
      // cout << "dpl: ";
      // for (int i = 0; i < n; ++i) {
      //   cout << dp_left.value(i) << " ";
      // }
      // cout << "\n";
      int idx = dp_left.search_left(l, m, {-h[m], value_r + (m + 1) * h[m]});
      dp_left.apply_range(idx, m, {-h[m], value_r + (m + 1) * h[m]});
      // cout << "dpl: ";
      // for (int i = 0; i < n; ++i) {
      //   cout << dp_left.value(i) << " ";
      // }
      // cout << "\n";
    }

    if (m == l) {
      dp_right.apply_range(m + 1, r, {OFFSET_SENTINEL, h[m]});
      dp_right.apply_range(m, m + 1, {0, h[m]});
    } else {
      dp_right.apply_range(m, m + 1, {0, value_l + h[m]});
      dp_right.apply_range(m + 1, r, {OFFSET_SENTINEL, h[m] * (m - l + 1)});
      int idx =
          dp_right.search_right(m + 1, r, {h[m], value_l - h[m] * (m - 1)});
      dp_right.apply_range(m + 1, idx + 1, {h[m], value_l - h[m] * (m - 1)});
    }

    // cout << l << ", " << r << "\n";
    // cout << "dpl: ";
    // for (int i = 0; i < n; ++i) {
    //   cout << dp_left.value(i) << " ";
    // }
    // cout << "\ndpr: ";
    // for (int i = 0; i < n; ++i) cout << dp_right.value(i) << " ";
    // cout << "\n";
  };
  traverse(0, n);
  return ans;
}

#ifndef EVAL
#include "grader.cpp"
#endif

Compilation message (stderr)

meetings.cpp: In member function 'void RMQ::build(std::vector<int>*)':
meetings.cpp:133:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  133 |     for (int i = 0; i < src->size(); ++i) {
      |                     ~~^~~~~~~~~~~~~
meetings.cpp:136:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  136 |     for (int i = 2, li = 1; i < 2 * src->size(); i = 2 * i, li += 1) {
      |                             ~~^~~~~~~~~~~~~~~~~
meetings.cpp:138:29: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  138 |       for (int j = 0; j + i <= src->size(); ++j) {
      |                       ~~~~~~^~~~~~~~~~~~~~
#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...