qwerty787788

Mo Tree

Sep 3rd, 2017
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.87 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class I {
  5.     private FastScanner in;
  6.     private PrintWriter out;
  7.  
  8.     int[] p;
  9.  
  10.     int get(int x) {
  11.         return p[x] == x ? x : (p[x] = get(p[x]));
  12.     }
  13.  
  14.     void unite(int x, int y) {
  15.         p[get(x)] = get(y);
  16.     }
  17.  
  18.     private void solve() {
  19.         int n = in.nextInt();
  20. //        Random rnd = new Random(123);
  21. //        p = new int[n];
  22. //        for (int i = 0; i < n; i++) {
  23. //            p[i] = i;
  24. //        }
  25.         men = new int[n];
  26.         for (int i = 0; i < n; i++) {
  27.             men[i] = in.nextInt();
  28.         }
  29.         f = new int[n];
  30.         int[] all = new int[n];
  31.         for (int i = 0; i < n; i++) {
  32.             f[i] = all[i] = in.nextInt();
  33.         }
  34.         Arrays.sort(all);
  35.         for (int i = 0; i < n; i++) {
  36.             f[i] = Arrays.binarySearch(all, f[i]);
  37.         }
  38.  
  39.         MoTree tree = new MoTree(n, new Solver());
  40.         for (int i = 0; i + 1 < n; i++) {
  41.             int fr = in.nextInt() - 1;
  42.             int to = in.nextInt() - 1;
  43.             tree.addEdge(fr, to);
  44.         }
  45.         int cnt = in.nextInt();
  46.         for (int i = 0; i < cnt; i++) {
  47.             Query q = new Query(in.nextInt() - 1, in.nextInt() - 1, i);
  48.             tree.addQuery(q);
  49.         }
  50.         res = new long[cnt];
  51.         curMens = new int[n];
  52.         curWem = new int[n];
  53.         tree.solve();
  54.         for (long z : res) {
  55.             out.println(z);
  56.         }
  57.     }
  58.  
  59.     long[] res;
  60.     long curSum;
  61.     int[] men;
  62.     int[] f;
  63.     int[] curMens;
  64.     int[] curWem;
  65.  
  66.     class Solver {
  67.         void addVertex(int v) {
  68.             if (men[v] == 1) {
  69.                 curMens[f[v]]++;
  70.                 curSum += curWem[f[v]];
  71.             } else {
  72.                 curWem[f[v]]++;
  73.                 curSum += curMens[f[v]];
  74.             }
  75.         }
  76.  
  77.         void removeVertex(int v) {
  78.             if (men[v] == 1) {
  79.                 curMens[f[v]]--;
  80.                 curSum -= curWem[f[v]];
  81.             } else {
  82.                 curWem[f[v]]--;
  83.                 curSum -= curMens[f[v]];
  84.             }
  85.         }
  86.  
  87.         void answerQuery(Query q) {
  88.             res[q.id] = curSum;
  89.         }
  90.     }
  91.  
  92.  
  93.     class Query {
  94.         int v, u, id;
  95.  
  96.         public Query(int v, int u, int id) {
  97.             this.v = v;
  98.             this.u = u;
  99.             this.id = id;
  100.         }
  101.  
  102.         int arrayL, arrayR, needLCA;
  103.  
  104.         @Override
  105.         public String toString() {
  106.             return "Query{" +
  107.                     "arrayL=" + arrayL +
  108.                     ", arrayR=" + arrayR +
  109.                     ", needLCA=" + needLCA +
  110.                     '}';
  111.         }
  112.     }
  113.  
  114.     class MoTree {
  115.         ArrayList<Integer>[] g;
  116.         ArrayList<Query> queries;
  117.         int n;
  118.         Solver s;
  119.  
  120.         MoTree(int n, Solver s) {
  121.             this.n = n;
  122.             g = new ArrayList[n];
  123.             for (int i = 0; i < n; i++) {
  124.                 g[i] = new ArrayList<>();
  125.             }
  126.             this.s = s;
  127.             queries = new ArrayList<>();
  128.         }
  129.  
  130.         void addEdge(int fr, int to) {
  131.             g[fr].add(to);
  132.             g[to].add(fr);
  133.         }
  134.  
  135.         void addQuery(Query q) {
  136.             queries.add(q);
  137.         }
  138.  
  139.         final int LOG = 20;
  140.         int[][] up;
  141.         int time;
  142.         int[] tin, tout;
  143.         int[] array;
  144.         int blockSize;
  145.  
  146.         void solve() {
  147.             up = new int[LOG][n];
  148.             time = 0;
  149.             tin = new int[n];
  150.             tout = new int[n];
  151.             blockSize = 2 * (int) Math.sqrt(n);
  152.             array = new int[2 * n];
  153.             dfs(0, 0);
  154.             for (int i = 1; i < LOG; i++) {
  155.                 for (int j = 0; j < n; j++) {
  156.                     up[i][j] = up[i - 1][up[i - 1][j]];
  157.                 }
  158.             }
  159.             for (Query q : queries) {
  160.                 if (tin[q.v] > tin[q.u]) {
  161.                     int tmp = q.v;
  162.                     q.v = q.u;
  163.                     q.u = tmp;
  164.                 }
  165.                 if (inside(q.v, q.u)) {
  166.                     q.arrayL = tin[q.v];
  167.                     q.needLCA = -1;
  168.                 } else {
  169.                     q.arrayL = tout[q.v];
  170.                     q.needLCA = lca(q.v, q.u);
  171.                 }
  172.                 q.arrayR = tin[q.u] + 1;
  173.             }
  174.             Collections.sort(queries, new Comparator<Query>() {
  175.                 @Override
  176.                 public int compare(Query o1, Query o2) {
  177.                     int p1 = o1.arrayL / blockSize, p2 = o2.arrayL / blockSize;
  178.                     if (p1 != p2) {
  179.                         return Integer.compare(p1, p2);
  180.                     }
  181.                     int v = p1 % 2 == 0 ? 1 : -1;
  182.                     return v * Integer.compare(o1.arrayR, o2.arrayR);
  183.                 }
  184.             });
  185. //            System.err.println("Array  = " + Arrays.toString(array));
  186. //            for (Query q : queries) {
  187. //                System.err.println(q);
  188. //            }
  189.             int it1 = 0, it2 = 0;
  190.             use = new int[n];
  191.             for (Query q : queries) {
  192.                 while (it1 < q.arrayL) {
  193.                     changeUse(array[it1++]);
  194.                 }
  195.                 while (it1 > q.arrayL) {
  196.                     changeUse(array[--it1]);
  197.                 }
  198.                 while (it2 < q.arrayR) {
  199.                     changeUse(array[it2++]);
  200.                 }
  201.                 while (it2 > q.arrayR) {
  202.                     changeUse(array[--it2]);
  203.                 }
  204.                 if (q.needLCA != -1) {
  205.                     changeUse(q.needLCA);
  206.                 }
  207.                 s.answerQuery(q);
  208.                 if (q.needLCA != -1) {
  209.                     changeUse(q.needLCA);
  210.                 }
  211.             }
  212.         }
  213.  
  214.         int[] use;
  215.  
  216.         void changeUse(int v) {
  217.             use[v] ^= 1;
  218.             if (use[v] == 1) {
  219.                 s.addVertex(v);
  220.             } else {
  221.                 s.removeVertex(v);
  222.             }
  223.         }
  224.  
  225.         void dfs(int v, int p) {
  226.             array[time] = v;
  227.             tin[v] = time++;
  228.             up[0][v] = p;
  229.             for (int i = 0; i < g[v].size(); i++) {
  230.                 int to = g[v].get(i);
  231.                 if (to == p) {
  232.                     continue;
  233.                 }
  234.                 dfs(to, v);
  235.             }
  236.             array[time] = v;
  237.             tout[v] = time++;
  238.         }
  239.  
  240.         boolean inside(int p, int v) {
  241.             return tin[v] >= tin[p] && tout[v] <= tout[p];
  242.         }
  243.  
  244.         int lca(int x, int y) {
  245.             for (int i = LOG - 1; i >= 0; i--) {
  246.                 if (!inside(up[i][x], y)) {
  247.                     x = up[i][x];
  248.                 }
  249.             }
  250.             return inside(x, y) ? x : up[0][x];
  251.         }
  252.     }
  253.  
  254.     private void run() {
  255.         try {
  256.             in = new FastScanner(new File("I.in"));
  257.             out = new PrintWriter(new File("I.out"));
  258.  
  259.             solve();
  260.  
  261.             out.close();
  262.         } catch (FileNotFoundException e) {
  263.             e.printStackTrace();
  264.         }
  265.     }
  266.  
  267.     private void runIO() {
  268.         in = new FastScanner(System.in);
  269.         out = new PrintWriter(System.out);
  270.  
  271.         solve();
  272.  
  273.         out.close();
  274.     }
  275.  
  276.     private class FastScanner {
  277.         BufferedReader br;
  278.         StringTokenizer st;
  279.  
  280.         FastScanner(File f) {
  281.             try {
  282.                 br = new BufferedReader(new FileReader(f));
  283.             } catch (FileNotFoundException e) {
  284.                 e.printStackTrace();
  285.             }
  286.         }
  287.  
  288.         FastScanner(InputStream f) {
  289.             br = new BufferedReader(new InputStreamReader(f));
  290.         }
  291.  
  292.         String next() {
  293.             while (st == null || !st.hasMoreTokens()) {
  294.                 String s = null;
  295.                 try {
  296.                     s = br.readLine();
  297.                 } catch (IOException e) {
  298.                     e.printStackTrace();
  299.                 }
  300.                 if (s == null)
  301.                     return null;
  302.                 st = new StringTokenizer(s);
  303.             }
  304.             return st.nextToken();
  305.         }
  306.  
  307.         boolean hasMoreTokens() {
  308.             while (st == null || !st.hasMoreTokens()) {
  309.                 String s = null;
  310.                 try {
  311.                     s = br.readLine();
  312.                 } catch (IOException e) {
  313.                     e.printStackTrace();
  314.                 }
  315.                 if (s == null)
  316.                     return false;
  317.                 st = new StringTokenizer(s);
  318.             }
  319.             return true;
  320.         }
  321.  
  322.         int nextInt() {
  323.             return Integer.parseInt(next());
  324.         }
  325.  
  326.         long nextLong() {
  327.             return Long.parseLong(next());
  328.         }
  329.  
  330.         double nextDouble() {
  331.             return Double.parseDouble(next());
  332.         }
  333.     }
  334.  
  335.     public static void main(String[] args) {
  336.         new I().runIO();
  337.     }
  338. }
Advertisement
Add Comment
Please, Sign In to add comment