Submission #1247192

#TimeUsernameProblemLanguageResultExecution timeMemory
1247192EJOI2019AndrewCatfish Farm (IOI22_fish)C++20
6 / 100
1071 ms131788 KiB
#include "fish.h"

#include <vector>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;

const ll INF = 1LL << 60;

class SegTree {
public:
  vector<ll> tree;
  int n;
  SegTree(int _n) : n(_n), tree(4 * _n, -INF) {}
  void update(int idx, ll val) {
    update(1, 0, n - 1, idx, val);
  }
  ll query(int left, int right) {
    if (left > right) return -INF;
    return query(1, 0, n - 1, left, right);
  }
private:
  void update(int node, int s, int e, int idx, ll val) {
    if (s == e) {
      tree[node] = val;
      return;
    }
    int m = (s + e) / 2;
    if (idx <= m) update(2 * node, s, m, idx, val);
    else update(2 * node + 1, m + 1, e, idx, val);
    tree[node] = max(tree[2 * node], tree[2 * node + 1]);
  }
  ll query(int node, int s, int e, int left, int right) {
    if (right < s || e < left) return -INF;
    if (left <= s && e <= right) return tree[node];
    int m = (s + e) / 2;
    return max(query(2 * node, s, m, left, right), query(2 * node + 1, m + 1, e, left, right));
  }
};

long long max_weights(int N, int M, vector<int> X, vector<int> Y, vector<int> W) {
  vector<vector<pair<int, ll>>> fish(N);
  for (int i = 0; i < M; i++) {
    fish[X[i]].push_back({Y[i], W[i]});
  }
  vector<vector<int>> possible(N);
  for (int i = 0; i < M; i++) {
    int col = X[i];
    int thresh = Y[i] + 1;
    possible[col].push_back(thresh);
    if (col - 1 >= 0) possible[col - 1].push_back(thresh);
    if (col + 1 < N) possible[col + 1].push_back(thresh);
  }
  for (int c = 0; c < N; c++) {
    possible[c].push_back(0);
    sort(possible[c].begin(), possible[c].end());
    auto it = unique(possible[c].begin(), possible[c].end());
    possible[c].resize(it - possible[c].begin());
  }
  vector<int> global_y(M + N + 2);
  vector<ll> global_sum(M + N + 2);
  vector<int> inn(N);
  vector<int> outt(N);
  int cnt = 0;
  for (int c = 0; c < N; c++) {
    auto &p = fish[c];
    p.push_back({N, 0});
    sort(p.begin(), p.end());
    int sz = p.size();
    ++cnt;
    global_y[cnt] = p[0].first + 1;
    global_sum[cnt] = p[0].second;
    inn[c] = cnt;
    for (int j = 1; j < sz; j++) {
      ++cnt;
      global_y[cnt] = p[j].first + 1;
      global_sum[cnt] = global_sum[cnt - 1] + p[j].second;
    }
    outt[c] = cnt;
  }
  auto get_sum_le = [&](int col, int val) -> ll {
    if (val < 0) return 0;
    if (col < 0 || col >= N) return 0;
    int l = inn[col], r = outt[col];
    auto it = upper_bound(global_y.begin() + l, global_y.begin() + r + 1, val + 1);
    int k = it - global_y.begin() - 1;
    if (k < l) return 0;
    return global_sum[k];
  };
  auto get_sum_range = [&](int col, int low, int high) -> ll {
    if (low > high) return 0;
    return get_sum_le(col, high) - get_sum_le(col, low - 1);
  };
  vector<vector<ll>> dp_inc(N + 1);
  vector<vector<ll>> dp_dec(N + 1);
  vector<map<int, ll>> closed_map(N + 1);
  closed_map[0][0] = 0;
  for (int i = 0; i < N; i++) {
    vector<int> Hcur = possible[i];
    int s = Hcur.size();
    vector<ll> new_inc(s, -INF);
    vector<ll> new_dec(s, -INF);
    map<int, ll> new_closed;
    vector<int> Hprev = (i == 0 ? vector<int>{0} : possible[i - 1]);
    vector<ll> prev_inc = (i == 0 ? vector<ll>{0} : dp_inc[i]);
    vector<ll> prev_dec = (i == 0 ? vector<ll>{-INF} : dp_dec[i]);
    int t = Hprev.size();
    int j0 = lower_bound(Hcur.begin(), Hcur.end(), 0) - Hcur.begin();
    if (j0 == s || Hcur[j0] != 0) j0 = -1;
    // from prev_inc
    {
      SegTree st(t);
      for (int j = 0; j < t; j++) {
        ll val = prev_inc[j] + get_sum_le(i, Hprev[j] - 1) - get_sum_le(i - 1, Hprev[j] - 1);
        st.update(j, val);
      }
      for (int k = 0; k < s; k++) {
        ll h = Hcur[k];
        ll const_k = -get_sum_le(i, h - 1) + get_sum_le(i - 1, h - 1);
        int pos = upper_bound(Hprev.begin(), Hprev.end(), h) - Hprev.begin() - 1;
        ll mx = st.query(0, pos);
        if (mx > -INF) new_inc[k] = max(new_inc[k], mx + const_k);
        int pos2 = lower_bound(Hprev.begin(), Hprev.end(), h) - Hprev.begin();
        mx = st.query(pos2, t - 1);
        if (mx > -INF) new_dec[k] = max(new_dec[k], mx + const_k);
      }
    }
    // from prev_dec
    {
      SegTree st(t);
      for (int j = 0; j < t; j++) {
        ll val = prev_dec[j] + get_sum_le(i, Hprev[j] - 1);
        st.update(j, val);
      }
      for (int k = 0; k < s; k++) {
        ll h = Hcur[k];
        ll const_k = -get_sum_le(i, h - 1);
        // skip for new_inc
        int pos2 = lower_bound(Hprev.begin(), Hprev.end(), h) - Hprev.begin();
        ll mx = st.query(pos2, t - 1);
        if (mx > -INF) new_dec[k] = max(new_dec[k], mx + const_k);
      }
    }
    // from closed_map[i] to new_inc and new_closed
    ll val0 = closed_map[i][0];
    if (val0 > -INF) {
      for (int k = 0; k < s; k++) {
        ll h = Hcur[k];
        if (h == 0) continue;
        ll rsum = get_sum_range(i - 1, 0, h - 1);
        ll lsum = get_sum_range(i, h, 0 - 1);
        new_inc[k] = max(new_inc[k], val0 + rsum + lsum);
      }
    }
    ll maxv = -INF;
    for (auto &p : closed_map[i]) {
      maxv = max(maxv, p.second);
    }
    if (j0 >= 0 && maxv > -INF) {
      ll value = maxv + get_sum_range(i, 0, 0 - 1) + 0;
      new_closed[0] = max(new_closed[0], value);
    }
    // update new_closed from prev_inc and prev_dec
    if (j0 >= 0) {
      for (int j = 0; j < t; j++) {
        if (prev_inc[j] == -INF) continue;
        ll value = prev_inc[j] + get_sum_range(i, 0, Hprev[j] - 1) + 0;
        int h_before = Hprev[j];
        new_closed[h_before] = max(new_closed[h_before], value);
      }
      for (int j = 0; j < t; j++) {
        if (prev_dec[j] == -INF) continue;
        ll value = prev_dec[j] + get_sum_range(i, 0, Hprev[j] - 1) + 0;
        int h_before = Hprev[j];
        new_closed[h_before] = max(new_closed[h_before], value);
      }
    }
    dp_inc[i + 1] = new_inc;
    dp_dec[i + 1] = new_dec;
    closed_map[i + 1] = new_closed;
  }
  ll ans = 0;
  for (auto v : dp_inc[N]) ans = max(ans, v);
  for (auto v : dp_dec[N]) ans = max(ans, v);
  for (auto &p : closed_map[N]) ans = max(ans, p.second);
  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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...