Advertisement
ATSTNG

Problem 7 / Only paths compression

Nov 19th, 2018
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.16 KB | None | 0 0
  1. import java.io.OutputStream;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.io.PrintWriter;
  6. import java.util.Arrays;
  7. import java.io.BufferedWriter;
  8. import java.util.InputMismatchException;
  9. import java.io.IOException;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.io.Writer;
  13. import java.io.OutputStreamWriter;
  14. import java.io.InputStream;
  15.  
  16. /**
  17.  * Built using CHelper plug-in
  18.  * Actual solution is at the top
  19.  *
  20.  * @author Rustam Musin (t.me/musin_acm)
  21.  */
  22. public class Main {
  23.     public static void main(String[] args) {
  24.         InputStream inputStream = System.in;
  25.         OutputStream outputStream = System.out;
  26.         InputReader in = new InputReader(inputStream);
  27.         OutputWriter out = new OutputWriter(outputStream);
  28.         Task7 solver = new Task7();
  29.         solver.solve(1, in, out);
  30.         out.close();
  31.     }
  32.  
  33.     static class Task7 {
  34.         IntIntPair[] a;
  35.         int n;
  36.         int[][] g;
  37.         Query[] queries;
  38.  
  39.         public void solve(int testNumber, InputReader in, OutputWriter out) {
  40.             readInput(in);
  41.             new Solver().solve();
  42.             for (Query q : queries) {
  43.                 out.printLine(q.fail ? "fail" : "ok");
  44.             }
  45.         }
  46.  
  47.         int find(IntIntPair[] a, IntIntPair p) {
  48.             return Arrays.binarySearch(a, p);
  49.         }
  50.  
  51.         void readInput(InputReader in) {
  52.             n = in.readInt();
  53.             a = new IntIntPair[n];
  54.             for (int i = 0; i < n; i++) {
  55.                 a[i] = IntIntPair.makePair(in.readInt(), in.readInt());
  56.             }
  57.             Arrays.sort(a);
  58.             int[] size = new int[n];
  59.             int[] dx = {-1, 0, 1, 0};
  60.             int[] dy = {0, 1, 0, -1};
  61.             for (IntIntPair p : a) {
  62.                 int cur = find(a, p);
  63.                 for (int d = 0; d < 4; d++) {
  64.                     int x = p.first + dx[d];
  65.                     int y = p.second + dy[d];
  66.                     int id = find(a, IntIntPair.makePair(x, y));
  67.                     if (id >= 0) {
  68.                         size[cur]++;
  69.                     }
  70.                 }
  71.             }
  72.             g = new int[n][];
  73.             for (int i = 0; i < n; i++) {
  74.                 g[i] = new int[size[i]];
  75.             }
  76.             for (IntIntPair p : a) {
  77.                 int cur = find(a, p);
  78.                 for (int d = 0; d < 4; d++) {
  79.                     int x = p.first + dx[d];
  80.                     int y = p.second + dy[d];
  81.                     int id = find(a, IntIntPair.makePair(x, y));
  82.                     if (id >= 0) {
  83.                         g[cur][--size[cur]] = id;
  84.                     }
  85.                 }
  86.             }
  87.             int queryCount = in.readInt();
  88.             queries = new Query[queryCount];
  89.             for (int i = 0; i < queryCount; i++) {
  90.                 int monsterCount = in.readInt();
  91.                 int weaponCount = in.readInt();
  92.                 int player = find(a, IntIntPair.makePair(in.readInt(), in.readInt()));
  93.                 int[] monsters = new int[monsterCount];
  94.                 for (int j = 0; j < monsterCount; j++) {
  95.                     monsters[j] = find(a, IntIntPair.makePair(in.readInt(), in.readInt()));
  96.                 }
  97.                 int[] weapons = new int[weaponCount];
  98.                 for (int j = 0; j < weaponCount; j++) {
  99.                     weapons[j] = find(a, IntIntPair.makePair(in.readInt(), in.readInt()));
  100.                 }
  101.                 queries[i] = new Query(i, player, weapons, monsters);
  102.             }
  103.         }
  104.  
  105.         class Solver {
  106.             List<Integer>[] tree;
  107.             int treeN;
  108.             boolean[] isActive;
  109.             List<Integer> notRemoved;
  110.             DSU dsu;
  111.  
  112.             void solve() {
  113.                 buildTree();
  114.                 dsu = new DSU();
  115.                 isActive = new boolean[n];
  116.                 notRemoved = new ArrayList<>();
  117.                 for (int i = 0; i < n; i++) {
  118.                     notRemoved.add(i);
  119.                 }
  120.                 dfs(1);
  121.             }
  122.  
  123.             void buildTree() {
  124.                 int log = 1;
  125.                 while (1 << log < queries.length) {
  126.                     log++;
  127.                 }
  128.                 treeN = 1 << log;
  129.                 tree = new List[2 * treeN];
  130.                 for (int i = 0; i < tree.length; i++) {
  131.                     tree[i] = new ArrayList<>();
  132.                 }
  133.                 for (int i = 0; i < queries.length; i++) {
  134.                     for (int w : queries[i].weapons) {
  135.                         tree[i + treeN].add(w);
  136.                     }
  137.                 }
  138.                 for (int i = treeN - 1; i > 0; i--) {
  139.                     List<Integer> both = new ArrayList<>();
  140.                     int leftAt = 0;
  141.                     int rightAt = 0;
  142.                     List<Integer> leftCh = tree[i * 2];
  143.                     List<Integer> rightCh = tree[i * 2 + 1];
  144.                     while (leftAt < leftCh.size() && rightAt < rightCh.size()) {
  145.                         if (leftCh.get(leftAt) == (int) rightCh.get(rightAt)) {
  146.                             both.add(leftCh.get(leftAt));
  147.                             leftAt++;
  148.                             rightAt++;
  149.                         } else if (leftCh.get(leftAt) < rightCh.get(rightAt)) {
  150.                             both.add(leftCh.get(leftAt++));
  151.                         } else {
  152.                             both.add(rightCh.get(rightAt++));
  153.                         }
  154.                     }
  155.                     while (leftAt < leftCh.size()) {
  156.                         both.add(leftCh.get(leftAt++));
  157.                     }
  158.                     while (rightAt < rightCh.size()) {
  159.                         both.add(rightCh.get(rightAt++));
  160.                     }
  161.                     tree[i] = both;
  162.                 }
  163.             }
  164.  
  165.             void dfs(int v) {
  166.                 int startActions = dsu.actions.size();
  167.                 List<Integer> newNotRemoved = new ArrayList<>();
  168.                 List<Integer> removed = new ArrayList<>();
  169.                 int at = 0;
  170.                 for (int x : notRemoved) {
  171.                     while (at < tree[v].size() && tree[v].get(at) < x) {
  172.                         at++;
  173.                     }
  174.                     if (at < tree[v].size() && tree[v].get(at) == x) {
  175.                         newNotRemoved.add(x);
  176.                     } else {
  177.                         isActive[x] = true;
  178.                         for (int to : g[x]) {
  179.                             if (isActive[to]) {
  180.                                 dsu.unite(x, to);
  181.                             }
  182.                         }
  183.                         removed.add(x);
  184.                     }
  185.                 }
  186.                 if (v < treeN) {
  187.                     List<Integer> old = notRemoved;
  188.                     notRemoved = newNotRemoved;
  189.                     dfs(v * 2);
  190.                     dfs(v * 2 + 1);
  191.                     notRemoved = old;
  192.                 } else {
  193.                     if (v - treeN < queries.length) {
  194.                         Query query = queries[v - treeN];
  195.                         for (int monster : query.monsters) {
  196.                             query.fail |= dsu.find(query.player) == dsu.find(monster);
  197.                         }
  198.                     }
  199.                 }
  200.                 for (int x : removed) {
  201.                     isActive[x] = false;
  202.                 }
  203.                 dsu.restore(startActions);
  204.             }
  205.  
  206.         }
  207.  
  208.         class Query {
  209.             int index;
  210.             int player;
  211.             int[] weapons;
  212.             int[] monsters;
  213.             boolean fail;
  214.  
  215.             Query(int index, int player, int[] weapons, int[] monsters) {
  216.                 this.index = index;
  217.                 this.player = player;
  218.                 this.weapons = weapons;
  219.                 this.monsters = monsters;
  220.                 Arrays.sort(weapons);
  221.                 Arrays.sort(monsters);
  222.             }
  223.  
  224.         }
  225.  
  226.         enum ActionType {
  227.             PARENT,
  228.             RANK,
  229.             ;
  230.         }
  231.  
  232.         class Action {
  233.             Task7.ActionType type;
  234.             int index;
  235.             int value;
  236.  
  237.             Action(Task7.ActionType type, int index, int value) {
  238.                 this.type = type;
  239.                 this.index = index;
  240.                 this.value = value;
  241.             }
  242.  
  243.         }
  244.  
  245.         class DSU {
  246.             int[] parent;
  247.             List<Action> actions = new ArrayList<>();
  248.  
  249.             DSU() {
  250.                 parent = new int[n];
  251. //            rank = new int[n];
  252.                 for (int i = 0; i < n; i++) {
  253.                     parent[i] = i;
  254. //                rank[i] = 1;
  255.                 }
  256.             }
  257.  
  258.             void saveChange(boolean parent, int index, int value) {
  259.                 if (parent) {
  260.                     actions.add(new Action(Task7.ActionType.PARENT, index, value));
  261.                 } else {
  262.                     actions.add(new Action(Task7.ActionType.RANK, index, value));
  263.                 }
  264.             }
  265.  
  266.             int find(int v) {
  267.                 if (parent[v] == v) {
  268.                     return v;
  269.                 }
  270.                 saveChange(true, v, parent[v]);
  271.                 return parent[v] = find(parent[v]);
  272.             }
  273.  
  274.             boolean unite(int u, int v) {
  275.                 u = find(u);
  276.                 v = find(v);
  277.                 if (u == v) {
  278.                     return false;
  279.                 }
  280. //            if (rank[u] > rank[v]) return unite(v, u);
  281.                 saveChange(true, u, parent[u]);
  282. //            saveChange(false, v, rank[v]);
  283.                 parent[u] = v;
  284. //            rank[v] = Math.max(rank[v], rank[u] + 1);
  285.                 return true;
  286.             }
  287.  
  288.             void restore(int leftActions) {
  289.                 while (actions.size() > leftActions) {
  290.                     Action action = actions.get(actions.size() - 1);
  291.                     actions.remove(actions.size() - 1);
  292.                     if (action.type == Task7.ActionType.PARENT) {
  293.                         parent[action.index] = action.value;
  294.                     }
  295. //                else rank[action.index] = action.value;
  296.                 }
  297.             }
  298.  
  299.         }
  300.  
  301.     }
  302.  
  303.     static class IntIntPair implements Comparable<IntIntPair> {
  304.         public final int first;
  305.         public final int second;
  306.  
  307.         public static IntIntPair makePair(int first, int second) {
  308.             return new IntIntPair(first, second);
  309.         }
  310.  
  311.         public IntIntPair(int first, int second) {
  312.             this.first = first;
  313.             this.second = second;
  314.         }
  315.  
  316.         public boolean equals(Object o) {
  317.             if (this == o) {
  318.                 return true;
  319.             }
  320.             if (o == null || getClass() != o.getClass()) {
  321.                 return false;
  322.             }
  323.  
  324.             IntIntPair pair = (IntIntPair) o;
  325.  
  326.             return first == pair.first && second == pair.second;
  327.         }
  328.  
  329.         public int hashCode() {
  330.             int result = first;
  331.             result = 31 * result + second;
  332.             return result;
  333.         }
  334.  
  335.         public String toString() {
  336.             return "(" + first + "," + second + ")";
  337.         }
  338.  
  339.         public int compareTo(IntIntPair o) {
  340.             int value = Integer.compare(first, o.first);
  341.             if (value != 0) {
  342.                 return value;
  343.             }
  344.             return Integer.compare(second, o.second);
  345.         }
  346.  
  347.     }
  348.  
  349.     static class OutputWriter {
  350.         private final PrintWriter writer;
  351.  
  352.         public OutputWriter(OutputStream outputStream) {
  353.             writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
  354.         }
  355.  
  356.         public OutputWriter(Writer writer) {
  357.             this.writer = new PrintWriter(writer);
  358.         }
  359.  
  360.         public void print(Object... objects) {
  361.             for (int i = 0; i < objects.length; i++) {
  362.                 if (i != 0) {
  363.                     writer.print(' ');
  364.                 }
  365.                 writer.print(objects[i]);
  366.             }
  367.         }
  368.  
  369.         public void printLine(Object... objects) {
  370.             print(objects);
  371.             writer.println();
  372.         }
  373.  
  374.         public void close() {
  375.             writer.close();
  376.         }
  377.  
  378.     }
  379.  
  380.     static class InputReader {
  381.         private InputStream stream;
  382.         private byte[] buf = new byte[1024];
  383.         private int curChar;
  384.         private int numChars;
  385.         private InputReader.SpaceCharFilter filter;
  386.  
  387.         public InputReader(InputStream stream) {
  388.             this.stream = stream;
  389.         }
  390.  
  391.         public int read() {
  392.             if (numChars == -1) {
  393.                 throw new InputMismatchException();
  394.             }
  395.             if (curChar >= numChars) {
  396.                 curChar = 0;
  397.                 try {
  398.                     numChars = stream.read(buf);
  399.                 } catch (IOException e) {
  400.                     throw new InputMismatchException();
  401.                 }
  402.                 if (numChars <= 0) {
  403.                     return -1;
  404.                 }
  405.             }
  406.             return buf[curChar++];
  407.         }
  408.  
  409.         public int readInt() {
  410.             int c = read();
  411.             while (isSpaceChar(c)) {
  412.                 c = read();
  413.             }
  414.             int sgn = 1;
  415.             if (c == '-') {
  416.                 sgn = -1;
  417.                 c = read();
  418.             }
  419.             int res = 0;
  420.             do {
  421.                 if (c < '0' || c > '9') {
  422.                     throw new InputMismatchException();
  423.                 }
  424.                 res *= 10;
  425.                 res += c - '0';
  426.                 c = read();
  427.             } while (!isSpaceChar(c));
  428.             return res * sgn;
  429.         }
  430.  
  431.         public boolean isSpaceChar(int c) {
  432.             if (filter != null) {
  433.                 return filter.isSpaceChar(c);
  434.             }
  435.             return isWhitespace(c);
  436.         }
  437.  
  438.         public static boolean isWhitespace(int c) {
  439.             return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
  440.         }
  441.  
  442.         public interface SpaceCharFilter {
  443.             public boolean isSpaceChar(int ch);
  444.  
  445.         }
  446.  
  447.     }
  448. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement