PloadyFree

Отбор на Чемпионат юга 2018. Задача F

Mar 20th, 2018
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.54 KB | None | 0 0
  1. package net.egork;
  2.  
  3. import net.egork.utils.io.InputReader;
  4. import net.egork.utils.io.OutputWriter;
  5.  
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. public class TaskF {
  10.     int n;
  11.     List<Integer>[] g;
  12.     int[] size;
  13.     int[] depth;
  14.     int[] parent;
  15.  
  16.     public void solve(int testNumber, InputReader in, OutputWriter out) {
  17.         n = in.readInt();
  18.         g = new List[n];
  19.         for (int i = 0; i < n; i++) {
  20.             g[i] = new ArrayList<>();
  21.         }
  22.         for (int i = 0; i < n - 1; i++) {
  23.             int u = in.readInt() - 1;
  24.             int v = in.readInt() - 1;
  25.             g[u].add(v);
  26.             g[v].add(u);
  27.         }
  28.         size = new int[n];
  29.         depth = new int[n];
  30.         parent = new int[n];
  31.         dfs(0);
  32.         int wayCount = in.readInt();
  33.         HLD hld = new HLD();
  34.         int[][] ways = new int[wayCount][2];
  35.         for (int i = 0; i < wayCount; i++) {
  36.             ways[i][0] = in.readInt() - 1;
  37.             ways[i][1] = in.readInt() - 1;
  38.             int lca = hld.lca(ways[i][0], ways[i][1]);
  39.             hld.add(lca, 1);
  40.         }
  41.         long answer = 0;
  42.         for (int i = 0; i < wayCount; i++) {
  43.             answer += hld.getSum(ways[i][0], ways[i][1]) - 1;
  44.         }
  45.         for (int i = 0; i < n; i++) {
  46.             long sum = hld.getSum(i, i);
  47.             answer -= sum * (sum - 1) / 2;
  48.         }
  49.         long result = wayCount * (wayCount - 1L) / 2 - answer;
  50.         out.print(result);
  51.     }
  52.  
  53.     void dfs(int v) {
  54.         size[v] = 1;
  55.         for (int to : g[v]) {
  56.             g[to].remove((Integer) v);
  57.             depth[to] = depth[v] + 1;
  58.             parent[to] = v;
  59.             dfs(to);
  60.             size[v] += size[to];
  61.         }
  62.     }
  63.  
  64.     class Fenwick {
  65.         int[] tree;
  66.  
  67.         Fenwick(int size) {
  68.             tree = new int[size + 1];
  69.         }
  70.  
  71.         void add(int at, int value) {
  72.             for (at++; at < tree.length; at += at & -at) {
  73.                 tree[at] += value;
  74.             }
  75.         }
  76.  
  77.         int get(int at) {
  78.             int s = 0;
  79.             for (at++; at > 0; at -= at & -at) {
  80.                 s += tree[at];
  81.             }
  82.             return s;
  83.         }
  84.  
  85.         int get(int l, int r) {
  86.             return get(r) - get(l - 1);
  87.         }
  88.     }
  89.  
  90.     class HLD {
  91.  
  92.         List<List<Integer>> paths;
  93.         int[] treeIndex;
  94.         int[] indexInTree;
  95.         Fenwick[] trees;
  96.  
  97.         HLD() {
  98.             paths = new ArrayList<>();
  99.             paths.add(new ArrayList<>());
  100.             indexInTree = new int[n];
  101.             treeIndex = new int[n];
  102.             initTrees(0, 0);
  103.  
  104.             initTrees();
  105.         }
  106.  
  107.         void initTrees(int root, int tree) {
  108.             indexInTree[root] = paths.get(tree).size();
  109.             paths.get(tree).add(root);
  110.             treeIndex[root] = tree;
  111.             for (int to : g[root]) {
  112.                 if (size[to] * 2 >= size[root]) {
  113.                     initTrees(to, tree);
  114.                 } else {
  115.                     paths.add(new ArrayList<>());
  116.                     initTrees(to, paths.size() - 1);
  117.                 }
  118.             }
  119.         }
  120.  
  121.         int head(int path) {
  122.             return paths.get(treeIndex[path]).get(0);
  123.         }
  124.  
  125.         void initTrees() {
  126.             trees = new Fenwick[paths.size()];
  127.             for (int i = 0; i < trees.length; i++) {
  128.                 trees[i] = new Fenwick(paths.get(i).size());
  129.             }
  130.         }
  131.  
  132.         int getSum(int u, int v) {
  133.             int s = 0;
  134.             while (treeIndex[u] != treeIndex[v]) {
  135.                 if (depth[head(u)] > depth[head(v)]) {
  136.                     int t = u;
  137.                     u = v;
  138.                     v = t;
  139.                 }
  140.                 s += trees[treeIndex[v]].get(indexInTree[v]);
  141.                 v = parent[head(v)];
  142.             }
  143.             s += trees[treeIndex[u]].get(
  144.                     Math.min(indexInTree[u], indexInTree[v]),
  145.                     Math.max(indexInTree[u], indexInTree[v])
  146.             );
  147.             return s;
  148.         }
  149.  
  150.         int lca(int u, int v) {
  151.             while (treeIndex[u] != treeIndex[v]) {
  152.                 if (depth[head(u)] > depth[head(v)]) {
  153.                     int t = u;
  154.                     u = v;
  155.                     v = t;
  156.                 }
  157.                 v = parent[head(v)];
  158.             }
  159.             return depth[v] < depth[u] ? v : u;
  160.         }
  161.  
  162.         void add(int at, int value) {
  163.             Fenwick tree = trees[treeIndex[at]];
  164.             tree.add(indexInTree[at], value);
  165.         }
  166.     }
  167. }
Advertisement
Add Comment
Please, Sign In to add comment