Submission #622897

#TimeUsernameProblemLanguageResultExecution timeMemory
622897evenvalueSeats (IOI18_seats)C++17
33 / 100
710 ms61220 KiB
#include "seats.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 = 1e15 + 10;
constexpr int kMod = 1e9 + 7;

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 sum = 0;
  int mini = 0;
  int cnt = 0;

  friend ostream &operator<<(ostream &os, const node &x);
};

ostream &operator<<(ostream &os, const node &x) {
  os << x.sum << ' ' << x.mini << ' ' << x.cnt;
  return os;
}

int H, W, n;
vector<int> R, C;
SegTree<node> st;
vector<int> get_value;

void give_initial_chart(const int H_, const int W_, std::vector<int> R_, std::vector<int> C_) {
  assert(H_ == 1);
  H = H_, W = W_;
  n = H * W;
  R = move(R_), C = move(C_);
  st = SegTree<node>(n, node(), [](const node &l, const node &r) {
    node ret{};
    ret.sum = l.sum + r.sum;
    if (l.mini == l.sum + r.mini) {
      ret.mini = l.mini;
      ret.cnt = l.cnt + r.cnt;
    } else if (l.mini < l.sum + r.mini) {
      ret.mini = l.mini;
      ret.cnt = l.cnt;
    } else {
      ret.mini = l.sum + r.mini;
      ret.cnt = r.cnt;
    }
    return ret;
  });
  get_value.resize(n);
  for (int i = 0; i < n; i++) {
    get_value[C[i]] = i;
  }
  for (int x = 0, i = C[0]; x < n; x++, i = C[x]) {
    const int left = (i == 0 or get_value[i - 1] > x ? 1 : -1);
    const int right = (i == n - 1 or get_value[i + 1] > x ? 1 : -1);
    st.set(x, {left + right, left + right, 1});
  }
}

int swap_seats(const int x, const int y) {
  swap(get_value[C[x]], get_value[C[y]]);
  swap(C[x], C[y]);
  for (int i = max(0, C[x] - 1); i <= min(n - 1, C[x] + 1); i++) {
    const int c = get_value[i];
    const int left = (i == 0 or get_value[i - 1] > c ? 1 : -1);
    const int right = (i == n - 1 or get_value[i + 1] > c ? 1 : -1);
    st.set(c, {left + right, left + right, 1});
  }
  for (int i = max(0, C[y] - 1); i <= min(n - 1, C[y] + 1); i++) {
    const int c = get_value[i];
    const int left = (i == 0 or get_value[i - 1] > c ? 1 : -1);
    const int right = (i == n - 1 or get_value[i + 1] > c ? 1 : -1);
    st.set(c, {left + right, left + right, 1});
  }
  return st.get(0, n - 1).cnt;
}
#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...