Stunning Garbanzo
open main menu
Part of series: PS

14942 BOJ

/ 3 min read

문제

접근

희소 배열과 이분탐색을 통해 해결하였다.

희소 배열을 통해 2^i번째 부모 노드 정보를 미리 저장해놓고, query()를 통해 log(N)의 시간에 n번째 부모를 찾을 수 있게 한다. 이후 각각의 노드들에 대하여, 이분탐색을 통해 n번째 부모 노드까지 도달 할 수 있는 없는지 판단하여 최대 도달가능 위치를 알아낸다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef const ll cll;
typedef queue<ll> qll;
typedef queue<pll> qpll;
typedef priority_queue<ll> pqll;
typedef priority_queue<pll> pqpll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<vll> vvll;
typedef vector<vpll> vvpll;
#define FOR1(a, A) for (ll a = 0; a < A; ++a)
#define FOR2(a, b, A, B)                                                       \
  for (ll a = 0; a < A; ++a)                                                   \
    for (ll b = 0; b < B; ++b)

cll N = 1e5, S = 15;
ll n, energy[N] = {}, depths[N] = {}, sums[N] = {}, sparse[S][N] = {{}},
      *parents = sparse[0];
vpll edges[N];

void findParent(ll node) {
  for (auto &p : edges[node]) {
    if (p.first == parents[node]) {
      continue;
    }

    sums[p.first] = sums[node] + p.second, parents[p.first] = node,
    depths[p.first] = depths[node] + 1;
    findParent(p.first);
  }
}

void fillSparse() {
  for (ll s = 1; s < S; ++s) {
    for (ll node = 0; node < n; ++node) {
      sparse[s][node] = sparse[s - 1][sparse[s - 1][node]];
    }
  }
}

ll query(ll node, ll amt) {
  for (ll s = 0; s < S; ++s) {
    if (amt & (1 << s)) {
      node = sparse[s][node];
    }
  }

  return node;
}

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  cin >> n;
  for (ll i = 0; i < n; ++i) {
    cin >> energy[i];
  }
  for (ll a, b, c, i = 0; i < n - 1; ++i) {
    cin >> a >> b >> c;
    --a, --b;
    edges[a].emplace_back(make_pair(b, c));
    edges[b].emplace_back(make_pair(a, c));
  }

  findParent(0);
  fillSparse();

  for (ll node = 0; node < n; ++node) {
    ll st = 0, en = depths[node], result;
    while (st <= en) {
      ll mid = (st + en) / 2, idx = query(node, mid);
      if (sums[node] - sums[idx] <= energy[node]) {
        st = mid + 1, result = idx;
      } else {
        en = mid - 1;
      }
    }

    cout << result + 1 << "\n";
  }

  return 0;
}