Advertisement
ThegeekKnight16

Petrol Stations

Jul 13th, 2024
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.64 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. const int MAXN = 7e4 + 10;
  5. const int border = (int)1e15;
  6. array<vector<pair<int, int>>, MAXN> grafo;
  7. array<int, MAXN> sub, prof, removed, fuel, fuelPai;
  8. vector<int> resp;
  9. struct SparseSeg
  10. {
  11. protected:
  12.     vector<int> seg, e, d;
  13.  
  14. public:
  15.  
  16.     SparseSeg() {seg.reserve((int)MAXN*log2(border)); e.reserve((int)MAXN*log2(border)); d.reserve((int)MAXN*log2(border));}
  17.  
  18.     int create()
  19.     {
  20.         seg.push_back(0);
  21.         e.push_back(0);
  22.         d.push_back(0);
  23.         return seg.size()-1;
  24.     }
  25.  
  26.     int getLeft(int pos)
  27.     {
  28.         if (e[pos] == 0) {int aux = create(); e[pos] = aux;}
  29.         return e[pos];
  30.     }
  31.  
  32.     int getRight(int pos)
  33.     {
  34.         if (d[pos] == 0) {int aux = create(); d[pos] = aux;}
  35.         return d[pos];
  36.     }
  37.  
  38.     void init()
  39.     {
  40.         seg.clear(); e.clear(); d.clear();
  41.         create(); create();
  42.     }
  43.  
  44.     void update(int pos, int ini, int fim, int id, int val)
  45.     {
  46.         if (id < ini || id > fim) return;
  47.         if (ini == fim)
  48.         {
  49.             seg[pos] += val;
  50.             return;
  51.         }
  52.         int m = (ini + fim) >> 1;
  53.         if (id <= m) update(getLeft(pos), ini, m, id, val);
  54.         else update(getRight(pos), m+1, fim, id, val);
  55.         seg[pos] = seg[e[pos]] + seg[d[pos]];
  56.     }
  57.  
  58.     int query(int pos, int ini, int fim, int p, int q)
  59.     {
  60.         if (q < ini || p > fim || pos == 0 || q < p) return 0;
  61.         if (p <= ini && fim <= q) return seg[pos];
  62.         int m = (ini + fim) >> 1;
  63.         return (query(e[pos], ini, m, p, q) + query(d[pos], m+1, fim, p, q));
  64.     }
  65. } carGoes;
  66.  
  67. void dfsInit(int v, int p)
  68. {
  69.     sub[v] = 1;
  70.  
  71.     for (auto [viz, pes] : grafo[v])
  72.     {
  73.         if (viz == p) continue;
  74.         if (removed[viz]) continue;
  75.         dfsInit(viz, v);
  76.         sub[v] += sub[viz];
  77.     }
  78. }
  79.  
  80. int findCentroid(int v, int p, int N)
  81. {
  82.     for (auto [viz, pes] : grafo[v])
  83.     {
  84.         if (viz == p) continue;
  85.         if (removed[viz]) continue;
  86.         if (sub[viz] > N/2) return findCentroid(viz, v, N);
  87.     }
  88.     return v;
  89. }
  90.  
  91. void dfsVem(int v, int p, int e, vector<int> &path, int K, int mult, vector<int> &close)
  92. {
  93.     prof[v] = prof[p] + e; fuel[v] = 1; if (prof[v] <= K) close.push_back(v);
  94.     path.push_back(v);
  95.  
  96.     for (auto [viz, pes] : grafo[v])
  97.     {
  98.         if (viz == p || removed[viz]) continue;
  99.         dfsVem(viz, v, pes, path, K, mult, close);
  100.     }
  101.  
  102.     path.pop_back(); resp[v] += ((fuel[v]-1) * mult);
  103.     if (prof[v] - prof[path[0]] > K)
  104.     {
  105.         int ini = 0, fim = path.size()-1;
  106.         while (ini < fim)
  107.         {
  108.             int m = (ini + fim) >> 1;
  109.             int x = path[m];
  110.             if (prof[v] - prof[x] <= K) fim = m;
  111.             else ini = m+1;
  112.         }
  113.         fuel[path[fim]] += fuel[v];
  114.     }
  115. }
  116.  
  117. void dfsSai(int v, int p, int K)
  118. {
  119.     fuelPai[v] = 0;
  120.     fuelPai[v] = carGoes.query(1, -border, border, prof[p]-K, prof[v]-K-1);
  121.     resp[p] += fuelPai[v] * sub[v];
  122.     carGoes.update(1, -border, border, prof[p], fuelPai[v]);
  123.  
  124.  
  125.     for (auto [viz, pes] : grafo[v])
  126.     {
  127.         if (viz == p || removed[viz]) continue;
  128.         dfsSai(viz, v, K);
  129.     }
  130.  
  131.     carGoes.update(1, -border, border, prof[p], -fuelPai[v]);
  132. }
  133.  
  134. void decompose(int v, int N, int K)
  135. {
  136.     carGoes.init();
  137.     dfsInit(v, N+1);
  138.     int c = findCentroid(v, v, sub[v]);
  139.     dfsInit(c, N+1); prof[c] = 0;
  140.     vector<vector<int>> close;
  141.     for (auto [viz, pes] : grafo[c])
  142.     {
  143.         close.emplace_back();
  144.         if (removed[viz]) continue;
  145.         vector<int> path(1, c);
  146.         dfsVem(viz, c, pes, path, K, sub[c] - sub[viz], close.back());
  147.         for (auto x : close.back()) carGoes.update(1, -border, border, -prof[x], fuel[x]);
  148.     }
  149.     carGoes.update(1, -border, border, 0, 1);
  150.     for (int i = 0; i < grafo[c].size(); i++)
  151.     {
  152.         auto [viz, pes] = grafo[c][i];
  153.         if (removed[viz]) continue;
  154.         for (auto x : close[i]) carGoes.update(1, -border, border, -prof[x], -fuel[x]);
  155.         dfsSai(viz, c, K);
  156.         for (auto x : close[i]) carGoes.update(1, -border, border, -prof[x], fuel[x]);
  157.     }
  158.     close.clear();
  159.  
  160.     removed[c] = 1;
  161.     for (auto [viz, pes] : grafo[c]) if (!removed[viz]) decompose(viz, N, K);
  162. }
  163.  
  164. int32_t main()
  165. {
  166.     ios_base::sync_with_stdio(false);
  167.     cin.tie(NULL);
  168.     int N, K;
  169.     cin >> N >> K;
  170.     resp.resize(N);
  171.     for (int i = 1; i < N; i++)
  172.     {
  173.         int X, Y, P;
  174.         cin >> X >> Y >> P;
  175.         grafo[X].emplace_back(Y, P);
  176.         grafo[Y].emplace_back(X, P);
  177.     }
  178.  
  179.     decompose(0, N, K);
  180.  
  181.     for (auto x : resp) cout << x << '\n';
  182. }
  183.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement