Submission #1347176

#TimeUsernameProblemLanguageResultExecution timeMemory
1347176model_codeTriangular Rainfall (JOI26_rainfall)C++20
100 / 100
1690 ms64208 KiB
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

template <typename T>
using vc = vector<T>;
using ll = long long;

#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define FOR(i, a, b) for (ll i = (a); i < (b); ++i)

template <typename T>
vc<int> argsort(const vc<T> &A) {
  vc<int> ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  vc<T> B(len(I));
  FOR(i, 0, len(I)) B[i] = A[I[i]];
  return B;
}

/*
定数区間管理で単調減少列を扱う
*/
struct S {
  int N;
  set<int> cut;
  vc<int> A;

  // 最初は INF で初期化
  S(int N, int init_val) : N(N), A(N) {
    cut.insert(0), cut.insert(N);
    A[0] = init_val;
  }

  // <= k
  int prev(int k) {
    auto it = cut.lower_bound(k + 1);
    if (it == cut.begin()) return -1;
    return *(::prev(it));
  }

  // >= k
  int next(int k) {
    auto it = cut.lower_bound(k);
    if (it == cut.end()) return N + 1;
    return *(it);
  }

  // L,...,R-1 を chmin(v)
  // return: 変更前の値
  vc<tuple<int, int, int>> chmin(int L, int R, int v) {
    split(L), split(R);
    if (A[L] <= v) return {};
    int p = L;
    vc<tuple<int, int, int>> rm;
    while (p < R && A[p] > v) {
      cut.erase(p);
      int q = next(p);
      rm.eb(p, q, A[p]);
      p = q;
    }
    cut.insert(L);
    A[L] = v;
    return rm;
  }

  void split(int k) {
    if (cut.count(k)) return;
    int l = prev(k);
    A[k] = A[l];
    cut.insert(k);
  }

  // vc<int> get_all() {
  //   vc<int> B(N);
  //   int v = A[0];
  //   FOR(i, N) {
  //     if (cut[i]) ::chmin(v, A[i]);
  //     B[i] = v;
  //   }
  //   return B;
  // }
};

const int INF = 1'010'000'000;

void solve() {
  ll L, N, K;
  cin >> L >> N >> K;

  vc<tuple<ll, ll, ll>> tri(N);
  FOR(i, 0, N) {
    ll a, b, c;
    cin >> a >> b >> c;
    tri[i] = {a, b, c};
  }

  // a, b を座圧, distinct になるようにする
  vc<ll> X, Y;
  {
    FOR(i, 0, N) X.eb(get<0>(tri[i]));
    auto I = argsort(X);
    FOR(i, 0, N) { get<0>(tri[I[i]]) = i; }
    X = rearrange(X, I);
  }
  {
    FOR(i, 0, N) Y.eb(get<1>(tri[i]));
    auto I = argsort(Y);
    FOR(i, 0, N) { get<1>(tri[I[i]]) = i; }
    Y = rearrange(Y, I);
  }

  // a+b+d について降順
  sort(all(tri), [&](auto &T1, auto &T2) -> bool {
    auto [a1, b1, d1] = T1;
    auto [a2, b2, d2] = T2;
    return X[a1] + Y[b1] + d1 > X[a2] + Y[b2] + d2;
  });

  vc<ll> ANS(K + 1);

  // [x1,x2]x[y,inf] のうち x+y<=t を満たす部分
  // 渡すのは座圧インデックス
  auto calc = [&](ll x1, ll x2, ll y, ll t) -> ll {
    x1 = X[x1];
    x2 = X[x2];
    y = Y[y];
    t -= y;
    if (t <= 0) return 0;
    auto f = [&](ll x) -> ll {
      ll ans = 0;
      ans += t * t;
      if (x <= t) ans -= (t - x) * (t - x);
      return ans;
    };
    return f(x2) - f(x1);
  };

  FOR(i, 0, K + 1) X.eb(INF), Y.eb(INF);

  // k 枚以上であるところ
  vc<S> dat;
  FOR(k, 0, K + 1) {
    int ini = (k == 0 ? 0 : N + k);
    dat.eb(S(N, ini));
  }

  for (auto &[a, b, d] : tri) {
    ll t = X[a] + Y[b] + d;
    vc<tuple<int, int, int>> rect;
    rect.eb(a, N, b);
    FOR(k, 1, K + 1) {
      vc<tuple<int, int, int>> nxt;
      for (auto &[l, r, v] : rect) {
        auto rm = dat[k].chmin(l, r, v);
        for (auto &[l1, r1, w] : rm) {
          nxt.eb(l1, r1, w);
          assert(w > v);
          ANS[k] -= calc(l1, r1, w, t);
          ANS[k] += calc(l1, r1, v, t);
        }
      }
      int e = (nxt.empty() ? a : get<1>(nxt.back()));
      if (e < N) nxt.eb(e, N, b);
      swap(rect, nxt);
    }
  }
  FOR(k, 1, K + 1) cout << ANS[k] << "\n";
}

signed main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  solve();
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...