Advertisement
SorahISA

Christmas Tree

Dec 28th, 2021
1,186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.09 KB | None | 0 0
  1. #pragma GCC optimize("Ofast", "unroll-loops")
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4.  
  5. #define int long long
  6. #define double long double
  7. using pii = pair<int, int>;
  8. template <typename T>
  9. using Prior = std::priority_queue<T>;
  10. template <typename T>
  11. using prior = std::priority_queue<T, vector<T>, greater<T>>;
  12.  
  13. #define X first
  14. #define Y second
  15. #define eb emplace_back
  16. #define ef push_front
  17. #define ee emplace
  18. #define pb pop_back
  19. #define pf pop_front
  20. #define SZ(x) (int)(x).size()
  21. #define ALL(x) begin(x), end(x)
  22. #define RALL(x) rbegin(x), rend(x)
  23.  
  24. #ifdef local
  25. #define debug(...) \
  26.     cerr << "\u001b[33m" << "LINE " << __LINE__ << ": (" << #__VA_ARGS__ << ") = ",\
  27.     _do(__VA_ARGS__),\
  28.     cerr << "\u001b[0m"
  29. template <typename T> void _do(T &&_t) {cerr << _t << "\n";}
  30. template <typename T, typename ...U> void _do(T &&_t, U &&..._u) {cerr << _t << ", "; _do(_u...);}
  31. #define fastIO()
  32. #else
  33. #define debug(...) void()
  34. #define fastIO() ios_base::sync_with_stdio(0), cin.tie(0)
  35. #endif
  36.  
  37. template <typename T> bool chmin(T &lhs, T rhs) {return lhs > rhs ? lhs = rhs, 1 : 0;}
  38. template <typename T> bool chmax(T &lhs, T rhs) {return lhs < rhs ? lhs = rhs, 1 : 0;}
  39.  
  40. const int lgmx = 18 + 5;
  41. const int maxn = 2E5 + 5;
  42.  
  43. int N;
  44. vector<int> adj[maxn], dep(maxn, 0);
  45. vector<vector<int>> anc(lgmx, vector<int>(maxn, 0));
  46.  
  47. vector<int> c_ch[maxn], c_fa(maxn), c_sz(maxn, 0), c_val(maxn, 0), c_val_fa(maxn, 0), c_vis(maxn, 0);
  48. vector<vector<int>> c_dis(lgmx, vector<int>(maxn, 0));
  49. vector<int> tmp_sz(maxn), tmp_max_adj(maxn);
  50.  
  51. int lca(int x, int y) {
  52.     if (dep[x] < dep[y]) swap(x, y);
  53.     for (int lay = lgmx-1; lay >= 0; --lay) {
  54.         if ((dep[x] - dep[y]) >> lay) x = anc[lay][x];
  55.     }
  56.     if (x == y) return x;
  57.     for (int lay = lgmx-1; lay >= 0; --lay) {
  58.         if (anc[lay][x] != anc[lay][y]) x = anc[lay][x], y = anc[lay][y];
  59.     }
  60.     return anc[0][x];
  61. }
  62.  
  63. int get_dist(int x, int y) {
  64.     return dep[x] + dep[y] - 2 * dep[lca(x, y)];
  65. }
  66.  
  67. int find_centroid(int now, int tot_sz, int par = 0) {
  68.     tmp_sz[now] = 1, tmp_max_adj[now] = 0;
  69.     int cent = 0;
  70.     for (int x : adj[now]) {
  71.         if (c_vis[x] or x == par) continue;
  72.         chmax(cent, find_centroid(x, tot_sz, now));
  73.         tmp_sz[now] += tmp_sz[x], chmax(tmp_max_adj[now], tmp_sz[x]);
  74.     }
  75.     chmax(tmp_max_adj[now], tot_sz - tmp_sz[now]);
  76.     if (2 * tmp_max_adj[now] <= tot_sz) chmax(cent, now);
  77.     return cent;
  78. }
  79.  
  80. void add_value(int id) {
  81.     for (int now = id, lay = 0; now; now = c_fa[now], ++lay) {
  82.         ++c_sz[now], c_val[now] += c_dis[lay][id];
  83.         if (c_fa[now]) c_val_fa[now] += c_dis[lay+1][id];
  84.     }
  85. }
  86.  
  87. int calc_cost(int id) {
  88.     int ans = c_val[id];
  89.     for (int now = id, lay = 0; c_fa[now]; now = c_fa[now], ++lay) {
  90.         ans += c_val[c_fa[now]] - c_val_fa[now] + (c_sz[c_fa[now]] - c_sz[now]) * c_dis[lay+1][id];
  91.     }
  92.     return ans;
  93. }
  94.  
  95. int move_centroid(int L, int R) {
  96.     int M = lca(L, R), ans = M, min_cost = calc_cost(M);
  97.     while (L != M) {
  98.         if (chmin(min_cost, calc_cost(L))) ans = L;
  99.         L = anc[0][L];
  100.     }
  101.     while (R != M) {
  102.         if (chmin(min_cost, calc_cost(R))) ans = R;
  103.         R = anc[0][R];
  104.     }
  105.     return ans;
  106.     /*
  107.     int M = lca(L, R), milo, mihi;
  108.     int len_l, len_r, cost_l, cost_r;
  109.     while (L != M and R != M) {
  110.         // debug("step1"s, L, M, R);
  111.         len_l = dep[L] - dep[M], len_r = dep[R] - dep[M];
  112.         milo = anc[__lg(len_l-1)][L], mihi = anc[__lg(len_r-1)][R];
  113.         cost_l = calc_cost(milo), cost_r = calc_cost(mihi);
  114.         if (cost_l < cost_r) R = anc[0][mihi];
  115.         else                 L = anc[0][milo];
  116.     }
  117.     if (L == M) swap(L, R);
  118.     R = M;
  119.     while (dep[L] - dep[R] > 1) {
  120.         // debug("step2"s, L, R);
  121.         len_l = dep[L] - dep[R];
  122.         milo = anc[__lg(len_l-1)][L], mihi = anc[0][milo];
  123.         cost_l = calc_cost(milo), cost_r = calc_cost(mihi);
  124.         if (cost_l < cost_r) R = milo;
  125.         else                 L = mihi;
  126.     }
  127.     return calc_cost(L) <= calc_cost(R) ? L : R;
  128.     */
  129. }
  130.  
  131. void dfs_init(int now, int par = 0) {
  132.     dep[now] = dep[par] + 1, anc[0][now] = par;
  133.     for (int x : adj[now]) {
  134.         if (x == par) continue;
  135.         dfs_init(x, now);
  136.     }
  137. }
  138.  
  139. void lca_build() {
  140.     for (int lay = 1; lay < lgmx; ++lay) {
  141.         for (int i = 1; i <= N; ++i) anc[lay][i] = anc[lay-1][anc[lay-1][i]];
  142.     }
  143. }
  144.  
  145. int centroid_build(int now, int siz) {
  146.     int cent = find_centroid(now, siz);
  147.     c_vis[cent] = 1;
  148.     // debug(now, siz, cent);
  149.     for (int x : adj[cent]) {
  150.         if (c_vis[x]) continue;
  151.         int ch_cent = centroid_build(x, siz - tmp_max_adj[x]);
  152.         c_ch[cent].eb(ch_cent), c_fa[ch_cent] = cent;
  153.     }
  154.     return cent;
  155. }
  156.  
  157. void centroid_dis_build() {
  158.     for (int i = 1; i <= N; ++i) {
  159.         for (int now = c_fa[i], lay = 1; now; now = c_fa[now], ++lay) {
  160.             c_dis[lay][i] = get_dist(i, now);
  161.         }
  162.     }
  163. }
  164.  
  165. void solve() {
  166.     cin >> N;
  167.    
  168.     vector<int> H(N), id(N);
  169.     for (int &x : H) cin >> x;
  170.     H.insert(begin(H), 0);
  171.     iota(ALL(id), 1);
  172.     sort(ALL(id), [&](int &x, int &y) {return H[x] < H[y];});
  173.    
  174.     for (int i = 0, u, v; i < N-1; ++i) {
  175.         cin >> u >> v;
  176.         adj[u].eb(v), adj[v].eb(u);
  177.     }
  178.     dfs_init(1), lca_build();
  179.     int c_root = centroid_build(1, N);
  180.     centroid_dis_build();
  181.    
  182.     // debug(c_root);
  183.     // for (int i = 1; i <= N; ++i) debug(i, dep[i], anc[0][i], c_fa[i], c_vis[i]);
  184.     // for (int lay = 0; lay < 3; ++lay) {
  185.         // for (int i = 1; i <= N; ++i) debug(lay, i, c_dis[lay][i]);
  186.     // }
  187.    
  188.     int ans = 0, cost, cent = c_root, root;
  189.     for (int i : id) {
  190.         add_value(i);
  191.         // for (int j = 1; j <= N; ++j) debug(j, c_sz[j], c_val[j], c_val_fa[j]);
  192.         root = move_centroid(cent, i);
  193.         cost = N * c_sz[c_root] - calc_cost(root);
  194.         // debug(i, H[i], root, cost, cost - H[i]);
  195.         chmax(ans, cost - H[i]);
  196.     }
  197.     cout << ans << "\n";
  198. }
  199.  
  200. int32_t main() {
  201.     fastIO();
  202.    
  203.     int t = 1; // cin >> t;
  204.     for (int _ = 1; _ <= t; ++_) {
  205.         solve();
  206.     }
  207.    
  208.     return 0;
  209. }
  210.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement