Submission #842625

#TimeUsernameProblemLanguageResultExecution timeMemory
842625WLZTruck Driver (IOI23_deliveries)C++17
100 / 100
1149 ms47160 KiB
#include "deliveries.h"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const ll LINF = (ll) 1e18;

struct node {
  int l, r;
  ll sum_t, sum_t_w, max_w, lazy;
  node *left, *right;
} *root;

node *build(int l, int r, const vector<int> &t, const vector<ll> &w) {
  if (l == r) return new node{l, r, t[l], t[l] * w[l], w[l], 0, 0, 0};
  node *left = build(l, (l + r) / 2, t, w), *right = build((l + r) / 2 + 1, r, t, w);
  return new node{l, r, left->sum_t + right->sum_t, left->sum_t_w + right->sum_t_w, max(left->max_w, right->max_w), 0, left, right};
}

void push(node *cur) {
  if (cur->lazy == 0) return;
  cur->sum_t_w += cur->lazy * cur->sum_t;
  cur->max_w += cur->lazy;
  if (cur->left) {
    cur->left->lazy += cur->lazy;
    cur->right->lazy += cur->lazy;
  }
  cur->lazy = 0;
}

void update(node *cur, int l, int r, int val) {
  push(cur);
  if (cur->l > r || cur->r < l) return;
  if (l <= cur->l && cur->r <= r) {
    cur->lazy += val;
    push(cur);
    return;
  }
  update(cur->left, l, r, val); update(cur->right, l, r, val);
  cur->sum_t = cur->left->sum_t + cur->right->sum_t;
  cur->sum_t_w = cur->left->sum_t_w + cur->right->sum_t_w;
  cur->max_w = max(cur->left->max_w, cur->right->max_w);
}

ll query(node *cur, int l, int r) {
  push(cur);
  if (cur->l > r || cur->r < l) return 0;
  if (l <= cur->l && cur->r <= r) return cur->sum_t_w;
  return query(cur->left, l, r) + query(cur->right, l, r);
}

int n, cur_hld_pos = 0;
ll pre_ans = 0, sum_w = 0;
vector<int> p, w, subtree_size, heavy, up_edge, hld_head, hld_pos, hld_rev_pos;
vector<ll> subtree_sum, depth;
vector< vector< pair<int, int> > > g;

int find_last_large(node *cur) {
  push(cur);
  if (cur->l == cur->r) return hld_rev_pos[cur->l];
  push(cur->left); push(cur->right);
  if (2ll * cur->right->max_w > sum_w + 1) return find_last_large(cur->right);
  return find_last_large(cur->left);
}

void dfs(int u) {
  subtree_size[u] = 1;
  subtree_sum[u] = w[u];
  for (auto &[v, t] : g[u]) {
    if (v == p[u]) continue;
    up_edge[v] = t;
    depth[v] = depth[u] + t;
    p[v] = u;
    dfs(v); 
    subtree_sum[u] += subtree_sum[v];
    subtree_size[u] += subtree_size[v];
    if (heavy[u] == -1 || subtree_size[v] > subtree_size[heavy[u]]) heavy[u] = v;
  }
}

void hld_decompose(int u, int head) {
  hld_head[u] = head;
  hld_rev_pos[cur_hld_pos] = u;
  hld_pos[u] = cur_hld_pos++;
  if (heavy[u] != -1) hld_decompose(heavy[u], head);
  for (auto &[v, t] : g[u]) {
    if (v != p[u] && v != heavy[u]) hld_decompose(v, v);
  }
}

void init(int N, std::vector<int> U, std::vector<int> V, std::vector<int> T, std::vector<int> W) {
  n = N; w = W; g.resize(n);
  for (int i = 0; i < n - 1; i++) {
    g[U[i]].push_back({V[i], T[i]});
    g[V[i]].push_back({U[i], T[i]});
  }
  p.assign(n, -1); subtree_size.resize(n); heavy.assign(n, -1); up_edge.assign(n, 0); depth.assign(n, 0); subtree_sum.assign(n, 0);
  dfs(0);
  hld_pos.reserve(n); hld_rev_pos.reserve(n); hld_head.resize(n);
  hld_decompose(0, 0);
  vector<int> hld_t(n); vector<ll> hld_w(n);
  for (int i = 0; i < n; i++) {
    hld_t[hld_pos[i]] = up_edge[i];
    hld_w[hld_pos[i]] = subtree_sum[i];
    pre_ans += subtree_sum[i] * up_edge[i];
    sum_w += w[i];
  }
  root = build(0, n - 1, hld_t, hld_w);
}

long long max_time(int S, int X) {
  int diff = X - w[S]; w[S] = X;
  pre_ans += (ll) diff * depth[S];
  sum_w += diff;
  int u = S;
  while (u != -1) {
    update(root, hld_pos[hld_head[u]], hld_pos[u], diff);
    u = p[hld_head[u]];
  }
  u = find_last_large(root);
  ll ans = pre_ans + depth[u] * (sum_w + 1);
  while (u != -1) {
    ans -= 2ll * query(root, hld_pos[hld_head[u]], hld_pos[u]);
    u = p[hld_head[u]];
  }
  return 2ll * 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...