Submission #1239846

#TimeUsernameProblemLanguageResultExecution timeMemory
1239846rxlfd314Tree (IOI24_tree)C++20
31 / 100
2097 ms45728 KiB
#include "tree.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ari2 = array<int, 2>;
using ari3 = array<int, 3>;
using arl2 = array<ll, 2>;
using arl3 = array<ll, 3>;
template <class T> using vt = vector<T>;
#define all(x) begin(x), end(x)
#define size(x) (int((x).size()))
#define REP(a,b,c,d) for(int a=(b);(d)>0?a<=(c):a>=(c);a+=(d))
#define FOR(a,b,c) REP(a,b,c,1)
#define ROF(a,b,c) REP(a,b,c,-1)

constexpr int mxN = 200005;
int N;
vt<int> P, W, adj[mxN];
int hson[mxN], szs[mxN];
int tin[mxN], tout[mxN], head[mxN], timer, rev_tin[mxN];

struct Node {
  ll mss;
  ari2 min_w;
  ll lz;
  Node operator+(const Node &other) {
    return {min(mss, other.mss), min(min_w, other.min_w), 0};
  }
} st[mxN<<2];
#define lc i << 1
#define rc lc | 1
void build(const int i = 1, const int tl = 0, const int tr = N-1) {
  if (tl == tr)
    st[i] = {LLONG_MAX, ari2{W[rev_tin[tl]], rev_tin[tl]}, 0};
  else {
    const int tm = tl + tr >> 1;
    build(lc, tl, tm);
    build(rc, tm+1, tr);
    st[i] = st[lc] + st[rc];
  }
}
void app(const int i, const ll lz) {
  st[i].mss += lz;
  st[i].lz += lz;
}
void push(const int i) {
  if (st[i].lz == 0)
    return;
  app(lc, st[i].lz);
  app(rc, st[i].lz);
  st[i].lz = 0;
}
void update_add(const int ql, const int qr, const ll v, const int i = 1, const int tl = 0, const int tr = N-1) {
  if (tl > qr || tr < ql)
    return;
  if (ql <= tl && tr <= qr)
    app(i, v);
  else {
    push(i);
    const int tm = tl + tr >> 1;
    update_add(ql, qr, v, lc, tl, tm);
    update_add(ql, qr, v, rc, tm+1, tr);
    st[i] = st[lc] + st[rc];
  }
}
void update_set(const int p, const int i = 1, const int tl = 0, const int tr = N-1) {
  if (tl == tr)
    st[i].min_w = {INT_MAX, -1};
  else {
    push(i);
    const int tm = tl + tr >> 1;
    if (p <= tm)
      update_set(p, lc, tl, tm);
    else
      update_set(p, rc, tm+1, tr);
    st[i] = st[lc] + st[rc];
  }
}
void update_mss(const int p, const ll v, const int i = 1, const int tl = 0, const int tr = N-1) {
  if (tl == tr)
    st[i].mss = v;
  else {
    push(i);
    const int tm = tl + tr >> 1;
    if (p <= tm)
      update_mss(p, v, lc, tl, tm);
    else
      update_mss(p, v, rc, tm+1, tr);
    st[i] = st[lc] + st[rc];
  }
}
Node query_path(const int ql, const int qr, const int i = 1, const int tl = 0, const int tr = N-1) {
  if (tl > qr || tr < ql)
    return {LLONG_MAX, ari2{INT_MAX, -1}, LLONG_MAX};
  if (ql <= tl && tr <= qr)
    return st[i];
  push(i);
  const int tm = tl + tr >> 1;
  return query_path(ql, qr, lc, tl, tm) + query_path(ql, qr, rc, tm+1, tr);
}
#undef lc
#undef rc
ll worst(int i) {
  ll ret = LLONG_MAX;
  for (; i >= 0; i = P[head[i]])
    ret = min(ret, query_path(tin[head[i]], tin[i]).mss);
  return ret;
}
void update_path(int i, const ll v) {
  for (; i >= 0; i = P[head[i]])
    update_add(tin[head[i]], tin[i], v);
} 
ll query(int L, int R) {
  ll ans = 0;
  build();
  const auto dfs = [&](auto &&self, const int i) -> int {
    if (tin[i] == tout[i]) {
      ans += 1ll * L * W[i];
      update_set(tin[i]);
      return L;
    }
    ll cur_sum = 0;
    for (const auto &j : adj[i])
      cur_sum += self(self, j);
    //cout << worst(0) << ' ' << cur_sum << ' ' << R << '\n';
    while (cur_sum > R) {
      const auto [w, k] = query_path(tin[i], tout[i]).min_w;
      ll v = worst(k);
      assert(k >= 0 && v >= L);
      ans += 1ll * w * min(cur_sum - R, v - L);
      update_path(k, -min(cur_sum - R, v - L));
      cur_sum -= min(cur_sum - R, v - L);
      v -= min(cur_sum - R, v - L);
      if (v == L)
        update_set(tin[k]);
    }
    update_mss(tin[i], cur_sum);
    return cur_sum;
  };
  dfs(dfs, 0);
  return ans;
}

void dfs_szs(const int i) {
  szs[i] = 1;
  hson[i] = -1;
  for (const auto &j : adj[i]) {
    dfs_szs(j);
    szs[i] += szs[j];
    if (hson[i] < 0 || szs[j] > szs[hson[i]])
      hson[i] = j;
  }
}
void dfs_hld(const int i) {
  rev_tin[tin[i] = timer++] = i;
  if (hson[i] >= 0) {
    head[hson[i]] = head[i];
    dfs_hld(hson[i]);
  }
  for (const auto &j : adj[i])
    if (j != hson[i]) {
      head[j] = j;
      dfs_hld(j);
    }
  tout[i] = timer - 1;
}

void init(vt<int> _P, vt<int> _W) {
  P = _P, W = _W, N = size(P);
  FOR(i, 1, N-1)
    adj[P[i]].push_back(i);
  dfs_szs(0);
  dfs_hld(0);
}
#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...