import java.io.*; import java.util.*; /** * This submission uses a quite dumb version of the add/max segment tree. */ public class bricks_mb_dumbtree { static class Event implements Comparable { final int x, yMin, yMax, change; Event(int x, int yMin, int yMax, int change) { this.x = x; this.yMin = yMin; this.yMax = yMax; this.change = change; } public int compareTo(Event that) { return x - that.x; } } static abstract class LazyTree { abstract void add(int left, int right, int change); abstract int max(); abstract int min(); static LazyTree newTree(int left, int right) { return left == right ? new Leaf(left) : new Node(left, right); } } static class Leaf extends LazyTree { final int index; int value; Leaf(int index) { this.index = index; } void add(int left, int right, int change) { if (left <= index && index <= right) { value += change; } } int max() { return value; } int min() { return value; } } static class Node extends LazyTree { final int left, right; final LazyTree leftN, rightN; int max, min; int add; Node(int left, int right) { this.left = left; this.right = right; int mid = (left + right) / 2; this.leftN = LazyTree.newTree(left, mid); this.rightN = LazyTree.newTree(mid + 1, right); } void add(int left, int right, int change) { if (right >= this.left && left <= this.right) { if (left <= this.left && right >= this.right) { this.add += change; } else { leftN.add(left, right, change); rightN.add(left, right, change); this.max = Math.max(leftN.max(), rightN.max()); this.min = Math.min(leftN.min(), rightN.min()); } } } int max() { return max + add; } int min() { return min + add; } } public static void main(String[] args) throws IOException { try (Input in = new Input()) { int n = in.nextInt(); // Read raw input, start coordinate compression int[] yy = new int[2 * n]; int[][] input = new int[n][4]; for (int i = 0; i < n; ++i) { for (int j = 0; j < 4; ++j) { input[i][j] = in.nextInt(); } yy[2 * i] = input[i][1]; yy[2 * i + 1] = input[i][1] + input[i][3] - 1; } // Create compressor ys Arrays.sort(yy); int newSize = 1; for (int i = 1; i < yy.length; ++i) { if (yy[i] != yy[newSize - 1]) { yy[newSize] = yy[i]; ++newSize; } } // Generate events Event[] events = new Event[2 * n]; for (int i = 0; i < n; ++i) { int yMin = Arrays.binarySearch(yy, 0, newSize, input[i][1]); int yMax = Arrays.binarySearch(yy, 0, newSize, input[i][1] + input[i][3] - 1); events[2 * i] = new Event(input[i][0], yMin, yMax, +1); events[2 * i + 1] = new Event(input[i][0] + input[i][2], yMin, yMax, -1); } Arrays.sort(events); // Process events LazyTree tree = LazyTree.newTree(0, newSize - 1); boolean ok = true; for (int i = 0; ok && i < events.length; ++i) { Event e = events[i]; // System.err.println("e: x = " + e.x + ", yMin = " + e.yMin + ", yMax = " + e.yMax + ", change = " + e.change); tree.add(e.yMin, e.yMax, e.change); if (i + 1 == events.length) { ok = tree.max() == 0; } else if (e.x != events[i + 1].x) { ok = tree.max() == 1 && tree.min() == 1; } } System.out.println(ok ? "yes" : "no"); } } private static class Input implements Closeable { private final BufferedReader in; private StringTokenizer st; Input() throws IOException { in = new BufferedReader(new InputStreamReader(System.in)); st = new StringTokenizer(in.readLine()); } int nextInt() throws IOException { while (!st.hasMoreTokens()) { st = new StringTokenizer(in.readLine()); } return Integer.parseInt(st.nextToken()); } public void close() throws IOException { in.close(); } } }