/** * ICPC Central Europe Regional Contest 2018 * Sample solution: Shooter Island * * An O(L * MAXX * log(MAXY)) solution - for each of MAXX columns, keeps * the list of monochromatic intervals in a TreeMap. * * @author Josef Cibulka */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.NavigableMap; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; public class island { StringTokenizer st = new StringTokenizer(""); BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); boolean hasNextToken() { try { while (!st.hasMoreTokens()) { String line = input.readLine(); if (line == null) return false; st = new StringTokenizer(line); } } catch (IOException ex) { throw new RuntimeException(ex); } return true; } String nextToken() { return (!hasNextToken()) ? null : st.nextToken(); } int nextInt() { return Integer.parseInt(nextToken()); } public static void main(String[] args) { new island().run(); } static final int MAXX = 50; static class Range { int pos; int end; int color; Range(int pos, int end, int color) { this.pos = pos; this.end = end; this.color = color; } @Override public String toString() { return "Range:" + pos + "-" + end + ": " + color; } } static class Columns { Column[] columns = new Column[MAXX + 2]; int colorCnt = 0; Columns() { for (int i = 0; i < MAXX + 2; ++i) columns[i] = new Column(); } // Get colors in column colNeigh between y1 and y2, but skip subintervals where // column col has colored intervals (without doing this, we may keep taking the // same large set of intervals from colNeigh over and over again). Set getNeighColors (Column col, Column colNeigh, int y1, int y2) { Set colors = new TreeSet(); List starts = col.getStarts(y1, y2); int gap_start = y1; for (int s : starts) { Range r = col.ranges.get(s); int gap_end = s; if (gap_end < y1 || gap_end < gap_start) continue; colors.addAll(colNeigh.getColors(gap_start, gap_end)); gap_start = r.end + 1; } if (gap_start <= y2) colors.addAll(colNeigh.getColors(gap_start, y2)); return colors; } void addRectangle(int x1, int y1, int x2, int y2) { Set colors = new TreeSet(); if(x1 > 0) colors.addAll(getNeighColors(columns[x1], columns[x1-1], y1, y2 )); for(int x = x1; x <=x2; ++x) { colors.addAll(columns[x].getColors(y1 - 1, y2 + 1)); } colors.addAll(getNeighColors(columns[x2], columns[x2+1], y1, y2 )); int newC; if(colors.isEmpty()) { for (int i = 0; i < MAXX + 2; ++i) columns[i].addColor(); newC = colorCnt++; } else { newC = union(colors); } for(int x = x1; x <=x2; ++x) { columns[x].addRange(y1, y2, newC); } } // All intervals of color oldC get color newC. void recolorAll (int oldC, int newC) { for (int i = 0; i <= MAXX; ++i) { columns[i].recolorAll(oldC, newC); } } // Replace colors with a single color; keep the color // used the largest number of times. int union(Set colors) { int max = -1; int maxCnt = -1; for (int color : colors) { int cnt = 0; for (int i = 0; i <= MAXX; ++i) { cnt += columns[i].colStart.get(color).size(); } if(cnt > maxCnt) { max = color; maxCnt = cnt; } } for (int color : colors) if (color != max) recolorAll(color, max); return max; } @Override public String toString() { String str = new String(); for (int i = 0; i <= MAXX; ++i) { str += "Column " + i + "\n"; str += columns[i]; } return str; } } static class Column { // Keys are starting points of intervals, values are the intervals. NavigableMap ranges = new TreeMap(); // colStart[c] = Set of starting positions of ranges of color c. List> colStart = new ArrayList>(); void addColor() { colStart.add(new TreeSet()); } // Add the interval [a,b] of the given color and remove all // intersecting and touching intervals. void addRange(int a, int b, int color) { List starts = getStarts (a - 1, b + 1); int newStart = a; int newEnd = b; if(!starts.isEmpty()) { newStart = Math.min(a, starts.get(0)); newEnd = Math.max(b, ranges.get(starts.get(starts.size()-1)).end); } for (Integer s : starts) { colStart.get(color).remove(s); ranges.remove(s); } colStart.get(color).add(newStart); ranges.put(newStart, new Range(newStart, newEnd, color)); } // Get colors intersecting the interval [a,b] (incl. endpoints). Set getColors (int a, int b) { Set res = new TreeSet(); List starts = getStarts(a, b); for (int s : starts) { res.add(ranges.get(s).color); } return res; } // Get starts of intervals intersecting the interval [a,b] (incl. endpoints). List getStarts (int a, int b) { List res = new ArrayList(); Integer tmp = ranges.floorKey(a); if(tmp != null) { Range pt = ranges.get(tmp); if(pt.end >= a) res.add(pt.pos); } Integer cur = ranges.ceilingKey(a); while(cur != null && cur <= b) { res.add(cur); cur = ranges.ceilingKey(cur + 1); } return res; } // Change color of the interval starting at start. void recolor (int start, int newc) { Range stRange = ranges.get(start); colStart.get(stRange.color).remove(start); stRange.color = newc; colStart.get(stRange.color).add(start); } // All intervals of color oldC get color newC. void recolorAll (int oldC, int newC) { List starts = new ArrayList(); starts.addAll(colStart.get(oldC)); for (int i : starts) recolor(i, newC); } int getColor(int a) { Integer tmp = ranges.floorKey(a); if(tmp == null) return -1; Range r = ranges.get(tmp); if(r.end >= a) return r.color; else return -1; } @Override public String toString() { String str = new String(); for (Range range : ranges.values()) str += range + "\n"; str += "Colors:\n"; for (int i = 0; i < colStart.size(); ++i) { str += i + ": "; Set col = colStart.get(i); for (int c : col) str += c + ","; str += "\n"; } return str; } } void run() { int q_cnt = nextInt(); Columns s = new Columns(); for (int i = 0; i < q_cnt; ++i) { int t = nextInt(); int x1 = nextInt(); int y1 = nextInt(); int x2 = nextInt(); int y2 = nextInt(); if (t == 0) { if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; } if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; } s.addRectangle (x1, y1, x2, y2); // System.out.println(s); } else { int color1 = s.columns[x1].getColor(y1); int color2 = s.columns[x2].getColor(y2); if(color1 == color2 && color1 != -1) System.out.println("1"); else System.out.println("0"); } } } }