답안 #757831

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
757831 2023-06-13T19:11:35 Z taher Transport (COCI19_transport) C++17
130 / 130
419 ms 30500 KB
#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

int n, poi, cnt, curCentroid;
int subSizes[N];
vector<array<long long, 2>> adj[N];
bool vis[N];
vector<long long> all, v[N], c[N], g[N];
long long ans = 0;
long long a[N];
long long fenw[2 * N];
int times[2 * N];

void modify(int x, long long add) {
  while (x < (int) all.size()) {
    if (times[x] != cnt) {
      times[x] = cnt;
      fenw[x] = 0;
    }
    fenw[x] += add;
    x |= (x + 1);
  }
}

long long get(int x) {
  long long sum = 0;
  while (x >= 0) {
    if (times[x] != cnt) {
      fenw[x] = 0;
    }
    sum += fenw[x];
    x = (x & (x + 1)) - 1;
  }
  return sum;
}

void initArrays() {
  for (int i = 0; i < n; i++) {
    vis[i] = false;
  }
  for (int i = 0; i < 2 * n; i++) {
    times[i] = -1;
  }
  return ;
}

int getSiz(int u, int prev) {
  subSizes[u] = 1;
  for (auto x : adj[u]) {
    if (!vis[x[0]] && x[0] != prev) {
      subSizes[u] += getSiz(x[0], u);
    }
  }
  return subSizes[u];
}

int locateCentroid(int u, int prev, int sz) {
  for (auto x : adj[u]) {
    if (vis[x[0]] || x[0] == prev) {
      continue;
    }
    if (subSizes[x[0]] > sz / 2) {
      return locateCentroid(x[0], u, sz);
    }
  }
  return u;
}

int centroid(int u, int prev) {
  int sz = getSiz(u, prev);
  return locateCentroid(u, prev, sz);
}

void dfs(int u, int prev, long long balance, long long minPrefixBalance, long long minSuffixBalance) {
  all.push_back(-minPrefixBalance + a[curCentroid]);
  v[poi].push_back(minPrefixBalance);
  minSuffixBalance += a[u];
  balance += a[u];
  all.push_back(balance);

  g[poi].push_back(minSuffixBalance);
  c[poi].push_back(balance);
  for (auto x : adj[u]) {
    if (x[0] == prev || vis[x[0]]) {
      continue;
    }
    balance += x[1];
    long long nMnPref = min(minPrefixBalance, balance);
    dfs(x[0], u, balance, nMnPref, min(0LL, minSuffixBalance) + x[1]);
    balance -= x[1];
  }
  return ;
}

void Decompose(int u, int prev) {
  u = centroid(u, prev);
  curCentroid = u;
  vis[u] = 1;
  poi = 0;
  cnt++;
  all.clear();
  for (auto x : adj[u]) {
    if (x[0] == prev || vis[x[0]]) {
      continue;
    }
    dfs(x[0], u, a[u] + x[1], a[u] + x[1], x[1]);
    ++poi;
  }
  // all.push_back(a[u]);
  sort(all.begin(), all.end());
  all.erase(unique(all.begin(), all.end()), all.end());

  auto Compress = [&](long long pts) {
    int x = lower_bound(all.begin(), all.end(), pts) - all.begin();
    return x;  
  };

  for (int i = 0; i < poi; i++) {
    for (int j = 0; j < (int) v[i].size(); j++) {
      long long minPrefixBalance = v[i][j] - a[u];
      if (minPrefixBalance + a[u] >= 0) {
        ans += 1;
      }
      if (minPrefixBalance < 0) {
        modify(Compress(-minPrefixBalance), +1);
      } else {
        modify(0, +1);
      }
    }
  }

  for (int i = 0; i < poi; i++) {
    for (int j = 0; j < (int) c[i].size(); j++) {
      long long minPrefixBalance = v[i][j] - a[u];
      if (minPrefixBalance < 0) {
        modify(Compress(-minPrefixBalance), -1);
      } else {
        modify(0, -1);
      }      
    }

    for (int j = 0; j < (int) c[i].size(); j++) {
      long long curBalance = c[i][j];
      long long minSuffixBalance = g[i][j];
      if (minSuffixBalance >= 0) {
        ans += 1;
        ans += get(Compress(curBalance));
      }
    }

    for (int j = 0; j < (int) c[i].size(); j++) {
      long long minPrefixBalance = v[i][j] - a[u];
      if (minPrefixBalance < 0) {
        modify(Compress(-minPrefixBalance), +1);
      } else {
        modify(0, +1);
      }
    }
  }

  for (int i = 0; i < poi; i++) {
    v[i].clear();
    c[i].clear();
    g[i].clear();
  }
  for (auto x : adj[u]) {
    if (!vis[x[0]] && x[0] != prev) {
      Decompose(x[0], u);
    }
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n;
  initArrays();
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  for (int i = 0; i < n - 1; i++) {
    int f, t, cost;
    cin >> f >> t >> cost;
    --f, --t;
    adj[f].push_back({t, -cost});
    adj[t].push_back({f, -cost});
  }
  Decompose(0, -1);
  cout << ans << '\n';
  return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 11 ms 10196 KB Output is correct
2 Correct 12 ms 10512 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 10580 KB Output is correct
2 Correct 17 ms 10836 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 137 ms 18964 KB Output is correct
2 Correct 127 ms 18008 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 185 ms 22224 KB Output is correct
2 Correct 206 ms 24172 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 274 ms 27360 KB Output is correct
2 Correct 315 ms 30500 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 85 ms 14196 KB Output is correct
2 Correct 55 ms 14404 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 99 ms 18452 KB Output is correct
2 Correct 133 ms 16640 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 217 ms 19720 KB Output is correct
2 Correct 194 ms 20248 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 262 ms 22968 KB Output is correct
2 Correct 295 ms 23648 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 419 ms 26640 KB Output is correct
2 Correct 366 ms 24668 KB Output is correct