Problem Link: LOJ3339

Solution

Sort the events by time.

Note that $w \leq 5$, which means that we can separate each edge into edges of weight $1$. Specifically, we can replace each node $i$ ($0$-indexed) with nodes $5i, 5i + 1, \dots, 5i + 4$ handling edges of weight $1 \dots 5$. Nodes $5i + j$ and $5i + (j + 1)$ for $0 \leq j < 4$ have an edge of weight $1$ and edges $u, v, w$ ($0$-indexed) are transformed into an edge $5u + (w - 1) \rightarrow 5v$ with weight $1$.

Now that all edge weights are $1$, we can use binary lifting to compute the answer. Let $jmp[i][u][v]$ represent the maximum total joy value if Xiao W travels for $2^i$ days from node $u$ to node $v$, besides the food festivals and initial node. We compute transitions as follows:

\[jmp[i][u][v] = \max_{0 \leq mid < 5n} (jmp[i - 1][u][mid] + jmp[i - 1][mid][v]).\]

Each transition takes $\mathcal{O}(n^3)$ time, so computing the binary jump takes $\mathcal{O}(n^3 \log T)$ time.

Now that we have the binary lift, we can compute $dp[t][v]$, which represents the maximum joy Xiao W can get by travelling for $t$ days and ending at node $v$, taking food festivals into consideration. We compute $dp$ for each food festival, as well as $t = 0$ and $t = T$. Let $joy[u][v]$ represent the maxiumum joy Xiao W gets when travelling from $u$ to $v$ in $t_i - t_{i - 1}$ days, computed using the same transitions above. Then, the transitions for $dp$ are

\[dp[t_i][u] = \max_{0 \leq v < 5n} (dp[t_{i - 1}][v] + joy[v][u]).\]

However, this leads to a time complexity of $\mathcal{O}(k n^3 \log T)$, because we have to compute $joy$, which takes $\mathcal{O}(n^3 \log T)$.

To make this faster, we can add new food festivals such that the difference between consecutive food festivals is a power of two, allowing us to use the previously-computed $jmp$ values without more computation. Using the same $dp$ transitions above, which takes $\mathcal{O}(n^2)$, we achieve a time complexity of $\mathcal{O}((n^3 + kn^2) \log T)$.

Implementation

/**
 * @author n685
 * @brief
 * @date 2024-07-31 11:59:57
 *
 *
 */
#include <bits/stdc++.h>

#ifdef LOCAL
#include "dd/debug.h"
#else
#define dbg(...) 42
#define dbgP(...) 420
#define dbgRP(...) 420420
void nline() {}
void bar() {}
#endif

template <class T> constexpr T INF = T{};
template <std::floating_point T>
constexpr T INF<T> = std::numeric_limits<T>::infinity();
template <> constexpr int INF<int> = 0x3f3f3f3f; // 1061109567
template <>
constexpr int64_t INF<int64_t> = 0x3f3f3f3f3f3f3f3f; // 4557430888798830399

constexpr int LG = std::bit_width<uint32_t>(1'000'000'000); // 30
template <class T> T &chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
  }
  return a;
}

struct Event {
  int64_t t;
  int x;
  int64_t y;
};

int main() {
#ifndef LOCAL
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::freopen("delicacy.in", "r", stdin);
  std::freopen("delicacy.out", "w", stdout);
#endif

  int n, m;
  int64_t t;
  int k;
  std::cin >> n >> m >> t >> k;
  std::vector<int64_t> c(5 * n);
  for (int i = 0; i < n; ++i) {
    std::cin >> c[5 * i];
  }
  std::array<std::vector<std::vector<int64_t>>, LG> jmp;
  jmp.fill(std::vector(5 * n, std::vector(5 * n, -INF<int64_t>)));
  for (int i = 0; i < n; ++i) {
    for (int j = 1; j <= 4; ++j) {
      jmp[0][5 * i + (j - 1)][5 * i + j] = 0;
    }
  }
  n = 5 * n;
  for (int i = 0; i < m; ++i) {
    int u, v, w;
    std::cin >> u >> v >> w;
    --u;
    --v;
    u = 5 * u;
    v = 5 * v;
    chmax(jmp[0][u + (w - 1)][v], c[v]);
  }
  std::vector<Event> pe;
  pe.emplace_back(0, -1, -1);
  int64_t evt = 0;
  for (int i = 0; i < k; ++i) {
    int64_t tt;
    int x;
    int64_t y;
    std::cin >> tt >> x >> y;
    x = 5 * (x - 1);
    if (tt != t) {
      pe.emplace_back(tt, x, y);
    } else {
      if (x == 0) {
        evt = y;
      }
    }
  }
  pe.emplace_back(t, 0, evt);
  std::ranges::sort(pe, {}, &Event::t);

  std::vector<Event> ev;
  ev.emplace_back(0, -1, -1);
  for (int i = 1; i < std::ssize(pe); ++i) {
    auto [tt, x, y] = pe[i];
    int64_t pt = ev.back().t;
    for (int j = LG - 1; j >= 0; --j) {
      if (tt - pt >= (int64_t{1} << j)) {
        ev.emplace_back(pt + (int64_t{1} << j), -1, -1);
        pt += int64_t{1} << j;
      }
    }
    ev.back().x = x;
    ev.back().y = y;
  }

  for (int l = 1; l < LG; ++l) {
    for (int mid = 0; mid < n; ++mid) {
      for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
          chmax(jmp[l][i][j], jmp[l - 1][i][mid] + jmp[l - 1][mid][j]);
        }
      }
    }
  }
  std::vector pre(n, -INF<int64_t>);
  pre[0] = c[0];
  for (int i = 1; i < std::ssize(ev); ++i) {
    auto [tt, x, y] = ev[i];
    int lg = std::bit_width<uint64_t>(tt - ev[i - 1].t) - 1;
    std::vector cur(n, -INF<int64_t>);
    for (int ini = 0; ini < n; ++ini) {
      for (int dest = 0; dest < n; ++dest) {
        chmax(cur[dest], pre[ini] + jmp[lg][ini][dest]);
      }
    }
    if (x != -1) {
      cur[x] += y;
    }
    pre.swap(cur);
  }
  if (pre[0] <= -INF<int64_t> / 2) {
    std::cout << "-1\n";
  } else {
    std::cout << pre[0] << '\n';
  }
}