제출 #1339503

#제출 시각아이디문제언어결과실행 시간메모리
1339503po_rag526Transport (COCI19_transport)C++20
0 / 100
0 ms0 KiB
#include <bits/stdc++.h>

using namespace std;

#define fr first
#define sc second

using ll = long long;
#define int ll

const int N = 100005;
vector<pair<int, int>> vec[N];
int a[N], sz[N];
bool is_centr[N];
ll rasp = 0;
vector<int> de_la_mine, pana_la_mine;

/*
pana_sus este cat imi mai trebuie ca sa ajung din mine pana in c
sum_sus = suma de petrol pana la c exclusiv (inclusiv eu) - suma drumurilor

cat_jos = cat petrol imi trebuie ca sa ajung pana in eu inclusiv
petrol_jos = cu cat petrol ajung pana in mine in acest caz minimal
*/

void dfs(int nod, int papa, int pana_sus, int sum_sus, int cat_jos, int petrol_jos) {
   if (pana_sus == 0) {
      de_la_mine.push_back(sum_sus);
   } else {
      de_la_mine.push_back(-1);
   }
   pana_la_mine.push_back(cat_jos);

   for (auto i : vec[nod]) {
      if (i.fr == papa || is_centr[i.fr]) {
         continue;
      }
      int n_pana_sus = max(0ll, pana_sus + i.sc - a[i.fr]);
      int n_sum_sus = sum_sus + a[i.fr] - i.sc;
      int n_cat_jos = cat_jos + max(0ll, i.sc - petrol_jos - a[nod]);
      int n_petrol_jos = max(0ll, petrol_jos + a[nod] - i.sc);
      dfs(i.fr, nod, n_pana_sus, n_sum_sus, n_cat_jos, n_petrol_jos);
   }
}

ll solve(vector<int> dlmn, vector<int> plmn) {
   ll ans = 0;
   sort(dlmn.begin(), dlmn.end());
   sort(plmn.begin(), plmn.end());
//   cout << "dlmn: ";
//   for (auto i : dlmn) {
//      cout << i << " ";
//   }
//   cout << '\n';
//   cout << "plmn: ";
//   for (auto j : plmn) {
//      cout << j << " ";
//   }
//   cout << '\n';
   int nr1 = dlmn.size();
   int p = 0;
   for (auto i : plmn) {
      while (p < dlmn.size() && dlmn[p] < i) {
         nr1 --;
         p ++;
      }
      ans += nr1;
   }
//   cout << "Ans: ";
//   cout << ans << '\n';
   return ans;
}

int find_centr(int nod, int papa, int target) {
   for (auto i : vec[nod]) {
      if (i.fr != papa && !is_centr[i.fr] && sz[i.fr] >= target) {
         return find_centr(i.fr, nod, target);
      }
   }
   return nod;
}

void dfs_sz(int nod, int papa) {
   sz[nod] = 1;
   for (auto i : vec[nod]) {
      if (i.fr != papa && !is_centr[i.fr]) {
         dfs_sz(i.fr, nod);
         sz[nod] += sz[i.fr];
      }
   }
}


/*
pana_sus este cat imi mai trebuie ca sa ajung din mine pana in c
sum_sus = suma de petrol pana la c exclusiv (inclusiv eu) - suma drumurilor

cat_jos = cat petrol imi trebuie ca sa ajung pana in eu inclusiv
petrol_jos = cu cat petrol ajung pana in mine in acest caz minimal
*/

void decomp(int lol) {
   dfs_sz(lol, 0);
   int c = find_centr(lol, 0, (sz[lol] + 1) / 2);
   is_centr[c] = 1;
   vector<int> take_in, take_out;
   //cout << c << '\n';
   take_in = {0};
   take_out = {0};
   ll ans = 0;
   for (auto i : vec[c]) {
      if (is_centr[i.fr]) {
         continue;
      }
      de_la_mine.clear();
      pana_la_mine.clear();
      dfs(i.fr, c, max(0ll, i.sc - a[i.fr]), a[i.fr] - i.sc, max(0ll, i.sc - a[c]), max(0ll, a[c] - i.sc));
      for (auto j : de_la_mine)
         take_in.push_back(j);
      for (auto j : pana_la_mine)
         take_out.push_back(j);
      ans += solve(de_la_mine, pana_la_mine);
   }
   ans = solve(take_in, take_out) - ans - 1;
   rasp += ans;
   // cout << c << " " << ans << '\n';
   for (auto i : vec[c]) {
      if (!is_centr[i.fr]) {
         decomp(i.fr);
      }
   }
}

signed main() {
   int n;
   cin >> n;
   for (int i = 1; i <= n; i ++) {
      cin >> a[i];
   }
   for (int i = 1; i < n; i ++) {
      int u, v, w;
      cin >> u >> v >> w;
      vec[u].push_back({v, w});
      vec[v].push_back({u, w});
   }
   decomp(1);
   cout << rasp << '\n';
}

/*
de_la_mine[x] = daca nu ajungi pana la c -1, altfel cu cata benzina ajungi in c
pana_la_mine[x] = cata benzina imi trebuie sa ajung pana in x daca incep cu rezervorul plin cu ce am in c
*/
#Verdict Execution timeMemoryGrader output
Fetching results...