/+ dub.sdl:
    name "E"
    dependency "dunkelheit" version="1.0.1"
+/

import std.stdio, std.algorithm, std.range, std.conv;
// import dkh.foundation, dkh.scanner, dkh.graph.maxflow;

int main() {
    Scanner sc = new Scanner(stdin);
    scope(exit) assert(!sc.hasNext);

    int n, m;
    sc.read(n, m);

    int[] x1 = new int[m];
    int[] x2 = new int[m];
    int[] y1 = new int[m];
    int[] y2 = new int[m];
    foreach (i; 0..m) {
        sc.read(x1[i], y1[i], x2[i], y2[i]);
        x2[i]++; y2[i]++;
    }

    int[] xv = x1 ~ x2 ~ [0];
    int[] yv = y1 ~ y2 ~ [0];

    xv = xv.sort.uniq.array;
    yv = yv.sort.uniq.array;

    int getX(int x) {
        return xv.assumeSorted.lowerBound(x).length.to!int;
    }
    int getY(int y) {
        return yv.assumeSorted.lowerBound(y).length.to!int;
    }

    int w = xv.length.to!int - 1;
    int h = yv.length.to!int - 1;

    bool[][] mp = new bool[][](h, w);
    foreach (i; 0..m) {
        int l = getX(x1[i]), r = getX(x2[i]);
        int d = getY(y1[i]), u = getY(y2[i]);

        foreach (x; l..r) {
            foreach (y; d..u) {
                mp[y][x] = true;
            }
        }
    }

    struct Edge {
        int to, rev;
        long cap;
    }

    void addEdge(Edge[][] g, int from, int to, long cap) {
        g[from] ~= Edge(to, g[to].length.to!int, cap);
        g[to] ~= Edge(from, g[from].length.to!int-1, 0);
    }

    auto g = new Edge[][](1 + w + h + 1);
    int sv = w + h, tv = sv + 1;

    foreach (i; 0..w) {
        addEdge(g, sv, i, xv[i + 1] - xv[i]);
    }
    foreach (i; 0..h) {
        addEdge(g, w + i, tv, yv[i + 1] - yv[i]);
    }

    foreach (i; 0..w) {
        foreach (j; 0..h) {
            if (mp[j][i]) {
                addEdge(g, i, w + j, 10L^^18);
            }
        }
    }

    writeln(maxFlow!(long, 0)(g, sv, tv).flow);

    return 0;
}
/* IMPORT /home/yosupo/Programs/dunkelheit/source/dkh/foundation.d */

// module dkh.foundation;

static if (__VERSION__ <= 2070) {
    /*
    Copied by https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d
    Copyright: Andrei Alexandrescu 2008-.
    License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
    */
    template fold(fun...) if (fun.length >= 1) {
        auto fold(R, S...)(R r, S seed) {
            import std.algorithm : reduce;
            static if (S.length < 2) {
                return reduce!fun(seed, r);
            } else {
                import std.typecons : tuple;
                return reduce!fun(tuple(seed), r);
            }
        }
    }

}
/* IMPORT /home/yosupo/Programs/dunkelheit/source/dkh/container/deque.d */
// module dkh.container.deque;

struct DequePayload(T) {
    import core.exception : RangeError;

    private T* _data;
    private uint start, len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        if (start + i < cap) return _data[start + i];
        else return _data[start + i - cap];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import std.algorithm : max;
        import std.conv : to;
        if (newCap <= cap) return;
        T* newData = cast(T*)GC.malloc(newCap * T.sizeof);
        foreach (i; 0..length) {
            newData[i] = this[i];
        }
        _data = newData; start = 0; cap = newCap.to!uint;
    }
    void clear() {
        start = len = 0;
    }
    import std.algorithm : max;
    void insertFront(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        if (start == 0) start += cap;
        start--; len++;
        this[0] = item;
    }
    void insertBack(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        len++;
        this[len-1] = item;
    }
    void removeFront() {
        assert(!empty, "Deque.removeFront: Deque is empty");
        start++; len--;
        if (start == cap) start = 0;
    }
    void removeBack() {
        assert(!empty, "Deque.removeBack: Deque is empty");
        len--;
    }
}

struct Deque(T, bool mayNull = true) {
    import core.exception : RangeError;
    import std.range : ElementType, isInputRange;
    import std.traits : isImplicitlyConvertible;

    alias Payload = DequePayload!T;
    Payload* _p;

    static if (!mayNull) @disable this();

    this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) {
        _p = new Payload();
        foreach (v; values) {
            insertBack(v);
        }
    }

    this(Range)(Range r)
    if (isInputRange!Range &&
    isImplicitlyConvertible!(ElementType!Range, T) &&
    !is(Range == T[])) {
        _p = new Payload();
        foreach (v; r) {
            insertBack(v);
        }
    }
    private this(Payload* p) { _p = p; }
    static Deque make() { return Deque(new Payload()); }

    private bool havePayload() const { return (!mayNull || _p); }
    @property bool empty() const { return (!havePayload || _p.empty); }
    @property size_t length() const { return (havePayload ? _p.length : 0); }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        assert(!empty, "Deque.opIndex: Deque is empty");
        return (*_p)[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void clear() { if (_p) _p.clear(); }

    void insertFront(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertFront(item);
    }
    void insertBack(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertBack(item);
    }
    alias opOpAssign(string op : "~") = insertBack;
    alias stableInsertBack = insertBack;

    void removeFront() {
        assert(!mayNull || _p, "Deque.removeFront: Deque is empty");
        _p.removeFront();
    }
    void removeBack() {
        assert(!mayNull || _p, "Deque.removeBack: Deque is empty");
        _p.removeBack();
    }
    alias stableRemoveBack = removeBack;

    alias Range = RangeT!(DequePayload!T);
    alias ConstRange = RangeT!(const DequePayload!T);
    alias ImmutableRange = RangeT!(immutable DequePayload!T);

    size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
        assert(start <= end && end <= length);
        return [start, end];
    }
    Range opIndex(size_t[2] rng) { return Range(_p, rng[0], rng[1]); }
    ConstRange opIndex(size_t[2] rng) const { return ConstRange(_p, rng[0], rng[1]); }
    ImmutableRange opIndex(size_t[2] rng) immutable { return ImmutableRange(_p, rng[0], rng[1]); }
    auto opIndex() inout { return this[0..$]; }

    static struct RangeT(QualifiedPayload) {
        alias A = QualifiedPayload;
        import std.traits : CopyTypeQualifiers;
        alias E = CopyTypeQualifiers!(A, T);
        A *p;
        size_t l, r;

        @property bool empty() const { return r <= l; }
        @property size_t length() const { return r - l; }
        alias opDollar = length;

        @property auto save() { return this; }

        ref inout(E) opIndex(size_t i) inout {
            version(assert) if (empty) throw new RangeError();
            return (*p)[l+i];
        }
        @property ref inout(E) front() inout { return this[0]; }
        @property ref inout(E) back() inout { return this[$-1]; }

        void popFront() {
            version(assert) if (empty) throw new RangeError();
            l++;
        }
        void popBack() {
            version(assert) if (empty) throw new RangeError();
            r--;
        }

        size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
            assert(start <= end && end <= length);
            return [start, end];
        }
        auto opIndex(size_t[2] rng) { return RangeT(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) const { return RangeT!(const A)(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) immutable { return RangeT!(immutable A)(p, l+rng[0], l+rng[1]); }
        auto opIndex() inout { return this[0..$]; }
    }
}

/* IMPORT /home/yosupo/Programs/dunkelheit/source/dkh/container/stackpayload.d */
// module dkh.container.stackpayload;

struct StackPayload(T, size_t MINCAP = 4) if (MINCAP >= 1) {
    import core.exception : RangeError;

    private T* _data;
    private uint len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    inout(T)[] data() inout { return (_data) ? _data[0..len] : null; }

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        return _data[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import core.stdc.string : memcpy;
        import std.conv : to;
        if (newCap <= cap) return;
        void* newData = GC.malloc(newCap * T.sizeof);
        cap = newCap.to!uint;
        if (len) memcpy(newData, _data, len * T.sizeof);
        _data = cast(T*)(newData);
    }
    void free() {
        import core.memory : GC;
        GC.free(_data);
    }

    void clear() {
        len = 0;
    }

    void insertBack(T item) {
        import std.algorithm : max;
        if (len == cap) reserve(max(cap * 2, MINCAP));
        _data[len++] = item;
    }
    alias opOpAssign(string op : "~") = insertBack;
    void removeBack() {
        assert(!empty, "StackPayload.removeBack: Stack is empty");
        len--;
    }
}

/* IMPORT /home/yosupo/Programs/dunkelheit/source/dkh/graph/maxflow.d */
// module dkh.graph.maxflow;

// import dkh.container.deque;

struct MaxFlowInfo(C) {
    C flow;
    bool[] dual;
}

MaxFlowInfo!(C) maxFlow(C, C EPS, T)(T g, size_t s, size_t t, C gap = C.max) {
    assert(s != t);
    import std.conv : to;
    int[] level = new int[g.length];
    int[] iter = new int[g.length];

    void bfs() {
        level[] = -1; level[s] = 0;
        auto que = Deque!int();
        que.insertBack(s.to!int);
        while (!que.empty) {
            int v = que.front; que.removeFront;
            foreach (e; g[v]) {
                if (e.cap <= EPS) continue;
                if (level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    que.insertBack(e.to);
                }
            }
        }
    }

    C dfs(int v, C f) {
        import std.algorithm : min;
        if (v == t) return f;
        C res = 0;
        auto edgeList = g[v][iter[v]..$];
        foreach (ref e; edgeList) {
            if (e.cap <= EPS) continue;
            if (level[v] >= level[e.to]) continue;
            C d = dfs(e.to, min(f, e.cap));
            e.cap -= d;
            g[e.to][e.rev].cap += d;
            res += d;
            f -= d;
            if (f == 0) break;
            iter[v]++;
        }
        return res;
    }

    C flow = 0;
    while (gap - flow > EPS) {
        bfs();
        if (level[t] < 0) break;
        iter[] = 0;
        while (true) {
            C f = dfs(s.to!int, gap - flow);
            if (!f) break;
            flow += f;
        }
    }

    import std.algorithm : map;
    import std.range : array;
    auto mfInfo = MaxFlowInfo!C();
    mfInfo.flow = flow;
    mfInfo.dual = level.map!"a == -1".array;
    return mfInfo;
}

MaxFlowInfo!(C) maxFlowSlow(C, T)(T g, int s, int t, C gap = C.max) {
    assert(s != t);
    import std.algorithm : map;
    import std.range : array;
    import std.conv : to;
    auto n = g.length;

    bool[] used = new bool[n];
    bool dfs(int v) {
        if (v == t) return true;
        used[v] = true;
        foreach (ref e; g[v]) {
            if (used[e.to]) continue;
            if (!e.cap) continue;
            if (dfs(e.to)) {
                e.cap -= 1;
                g[e.to][e.rev].cap += 1;
                return true;
            }
        }
        return false;
    }

    C flow = 0;
    while (flow < gap) {
        used[] = false;
        if (!dfs(s)) break;
        flow++;
    }
    auto mfInfo = MaxFlowInfo!C();
    mfInfo.flow = flow;
    mfInfo.dual = used.map!"!a".array;
    return mfInfo;
}

/* IMPORT /home/yosupo/Programs/dunkelheit/source/dkh/scanner.d */
// module dkh.scanner;

// import dkh.container.stackpayload;

class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray;
    import std.algorithm : map;
    private File f;

    this(File f) {
        this.f = f;
    }
    private char[512] lineBuf;
    private char[] line;
    private bool succW() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (!line.empty && line.front.isWhite) {
            line.popFront;
        }
        return !line.empty;
    }
    private bool succ() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (true) {
            while (!line.empty && line.front.isWhite) {
                line.popFront;
            }
            if (!line.empty) break;
            line = lineBuf[];
            f.readln(line);
            if (!line.length) return false;
        }
        return true;
    }

    private bool readSingle(T)(ref T x) {
        import std.algorithm : findSplitBefore;
        import std.string : strip;
        import std.conv : parse;
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {

                auto r = line.findSplitBefore(" ");
                x = r[0].strip.dup;
                line = r[1];
            } else static if (isStaticArray!T) {
                foreach (i; 0..T.length) {
                    assert(succW());
                    x[i] = line.parse!E;
                }
            } else {
                StackPayload!E buf;
                while (succW()) {
                    buf ~= line.parse!E;
                }
                x = buf.data;
            }
        } else {
            x = line.parse!T;
        }
        return true;
    }

    int unsafeRead(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }

    void read(Args...)(auto ref Args args) {
        import std.exception : enforce;
        static if (args.length != 0) {
            enforce(readSingle(args[0]));
            read(args[1..$]);
        }
    }

    bool hasNext() {
        return succ();
    }
}

/*
This source code generated by dunkelheit and include dunkelheit's source code.
dunkelheit's Copyright: Copyright (c) 2016- Kohei Morita. (https://github.com/yosupo06/dunkelheit)
dunkelheit's License: MIT License(https://github.com/yosupo06/dunkelheit/blob/master/LICENSE.txt)
*/

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MaxFlow(Capa) {
  enum Capa wEPS = 0;
  enum Capa wINF = 10L^^18;
  int n, m;
  int[][] g;
  int[] zu;
  Capa[] capa;
  Capa tof;
  int[] lev, see, que;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; zu = []; capa = [];
    lev = new int[n]; see = new int[n]; que = new int[n];
  }
  void addEdge(int u, int v, Capa w0, Capa w1 = 0) {
    g[u] ~= m; zu ~= v; capa ~= w0; ++m;
    g[v] ~= m; zu ~= u; capa ~= w1; ++m;
  }
  Capa augment(int src, int ink, Capa flo) {
    if (src == ink) return flo;
    foreach (i; g[src][see[src] .. $]) {
      if (capa[i] > wEPS && lev[src] < lev[zu[i]]) {
        Capa f = augment(zu[i], ink, min(flo, capa[i]));
        if (f > wEPS) { capa[i] -= f; capa[i ^ 1] += f; return f; }
      }
      ++see[src];
    }
    return 0;
  }
  bool dinic(int src, int ink, Capa flo = wINF) {
    for (tof = 0; tof + wEPS < flo; ) {
      int[] q;
      lev[] = -1;
     dinicBFS:
      for (lev[src] = 0, q ~= src; !q.empty; ) {
        int u = q.front; q.popFront;
        foreach (i; g[u]) {
          int v = zu[i];
          if (capa[i] > wEPS && lev[v] == -1) {
            lev[v] = lev[u] + 1; q ~= v;
            if (v == ink) break dinicBFS;
          }
        }
      }
      if (lev[ink] == -1) return false;
      see[] = 0;
      for (; ; ) {
        Capa f = augment(src, ink, flo - tof);
        if (f <= wEPS) break;
        tof += f;
      }
    }
    return true;
  }
}

long N;
int M;
long[] XA, YA, XB, YB;

void main() {
  try {
    for (; ; ) {
      N = readLong();
      M = readInt();
      XA = new long[M];
      YA = new long[M];
      XB = new long[M];
      YB = new long[M];
      foreach (i; 0 .. M) {
        XA[i] = readLong() - 1;
        YA[i] = readLong() - 1;
        XB[i] = readLong();
        YB[i] = readLong();
      }

      auto xs = [0L, N] ~ XA.dup ~ XB.dup;
      auto ys = [0L, N] ~ YA.dup ~ YB.dup;
      xs = xs.sort.uniq.array;
      ys = ys.sort.uniq.array;
      const H = cast(int)(xs.length) - 1;
      const W = cast(int)(xs.length) - 1;
      auto board = new bool[][](H, W);
      foreach (i; 0 .. M) {
        const ea = xs.lowerBound(XA[i]);
        const fa = ys.lowerBound(YA[i]);
        const eb = xs.lowerBound(XB[i]);
        const fb = ys.lowerBound(YB[i]);
        foreach (e; ea .. eb) foreach (f; fa .. fb) {
          board[e][f] = true;
        }
      }
      debug {
        writeln("xs = ", xs);
        writeln("ys = ", ys);
        foreach (e; 0 .. H) {
          foreach (f; 0 .. W) {
            write(board[e][f] ? '#' : '.');
          }
          writeln();
        }
      }

      auto mf = new MaxFlow!long(2 + H + W);
      foreach (e; 0 .. H) {
        mf.addEdge(0, 2 + e, xs[e + 1] - xs[e]);
      }
      foreach (f; 0 .. W) {
        mf.addEdge(2 + H + f, 1, ys[f + 1] - ys[f]);
      }
      foreach (e; 0 .. H) foreach (f; 0 .. W) {
        if (board[e][f]) {
          mf.addEdge(2 + e, 2 + H + f, MaxFlow!long.wINF);
        }
      }
      mf.dinic(0, 1);
      writeln(mf.tof);
    }
  } catch (EOFException e) {
  }
}


import std.algorithm;
import std.conv;
import std.random;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int n;
	while (readf !(" %s") (n) > 0)
	{
		rndGen.seed (1235);
		auto h = new ulong [n];
		foreach (ref c; h)
		{
			c = uniform (1, ulong.max);
		}

		alias Segment = Tuple !(int, q{lo}, int, q{hi});
		auto a = new Segment [n];
		auto b = new Segment [n];
		foreach (i; 0..n)
		{
			readf !(" %s %s %s %s")
			    (a[i].lo, a[i].hi, b[i].lo, b[i].hi);
		}
		long res = 0;

		alias Event = Tuple !(int, q{pos}, int, q{id});

		ulong [] calc (const ref Segment [] a)
		{
			Event [] events;
			foreach (i, const ref s; a)
			{
				events ~= Event (s.lo * 2 + 0, i.to !(int));
				events ~= Event (s.hi * 2 + 1, i.to !(int));
			}
			sort (events);

			auto mark = new ulong [n];
			auto rem = new ulong [n];
			ulong addCur = 0;
			ulong remCur = 0;
			foreach (const ref e; events)
			{
				bool isAdd = !(e.pos & 1);
				if (isAdd)
				{
					addCur ^= h[e.id];
					rem[e.id] = remCur;
				}
				else
				{
					mark[e.id] = addCur ^ rem[e.id];
					remCur ^= h[e.id];
				}
			}
			debug {writeln (mark);}
			return mark;
		}

		writeln (equal (calc (a), calc (b)) ? "YES" : "NO");
	}
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

void bChmax(T)(T[] bit, int pos, T val)
in {
  assert(0 <= pos && pos < bit.length, "bChmax: 0 <= pos < |bit| must hold");
}
do {
  for (int x = pos; x < bit.length; x |= x + 1) {
    chmax(bit[x], val);
  }
}

// max of [0, pos)
T bMax(T)(T[] bit, int pos)
in {
  assert(0 <= pos && pos <= bit.length, "bMax: 0 <= pos <= |bit| must hold");
}
do {
  T ret = -1;
  for (int x = pos - 1; x >= 0; x = (x & (x + 1)) - 1) {
    chmax(ret, bit[x]);
  }
  return ret;
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      auto SA = new long[N];
      auto TA = new long[N];
      auto SB = new long[N];
      auto TB = new long[N];
      foreach (i; 0 .. N) {
        SA[i] = readLong();
        TA[i] = readLong();
        SB[i] = readLong();
        TB[i] = readLong();
      }

      bool ans = true;
      foreach (phase; 0 .. 2) {
        auto xs = SA.dup ~ TA.dup ~ SB.dup ~ TB.dup;
        xs = xs.sort.uniq.array;
        const xsLen = cast(int)(xs.length);

        auto lecsSA = iota(N).array;
        auto lecsTA = iota(N).array;
        lecsSA.sort!((i, j) => (SA[i] < SA[j]));
        lecsTA.sort!((i, j) => (TA[i] < TA[j]));

        auto bit = new long[xsLen];
        bit[] = -1;
        int posI;
        foreach (j; lecsSA) {
          for (; posI < N && TA[lecsTA[posI]] < SA[j]; ++posI) {
            const i = lecsTA[posI];
            debug {
              writeln("add i = ", i);
            }
            const key = xs.lowerBound(SB[i]);
            bit.bChmax(key, TB[i]);
          }
          {
            debug {
              writeln("check j = ", j);
            }
            const key = xs.lowerBound(TB[j]);
            const res = bit.bMax(key + 1);
            if (res >= SB[j]) {
              debug {
                writefln("found j = %s, res = %s", j, res);
              }
              ans = false;
            }
          }
        }

        swap(SA, SB);
        swap(TA, TB);
      }
      writeln(ans ? "YES" : "NO");
    }
  } catch (EOFException e) {
  }
}

import std.algorithm;
import std.conv;
import std.random;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int n;
	while (readf !(" %s") (n) > 0)
	{
		rndGen.seed (1235);
		auto h = new ulong [n];
		foreach (ref c; h)
		{
			c = uniform (1, ulong.max);
		}

		alias Segment = Tuple !(int, q{lo}, int, q{hi});
		auto a = new Segment [n];
		auto b = new Segment [n];
		foreach (i; 0..n)
		{
			readf !(" %s %s %s %s")
			    (a[i].lo, a[i].hi, b[i].lo, b[i].hi);
		}
		long res = 0;

		alias Event = Tuple !(int, q{pos}, int, q{id});

		ulong [] calc (const ref Segment [] a)
		{
			Event [] events;
			foreach (i, const ref s; a)
			{
				events ~= Event (s.lo * 2 + 1, i.to !(int));
				events ~= Event (s.hi * 2 + 0, i.to !(int));
			}
			sort (events);

			auto mark = new ulong [n];
			auto rem = new ulong [n];
			ulong addCur = 0;
			ulong remCur = 0;
			foreach (const ref e; events)
			{
				bool isAdd = e.pos & 1;
				if (isAdd)
				{
					addCur ^= h[e.id];
					rem[e.id] = remCur;
				}
				else
				{
					mark[e.id] = addCur ^ rem[e.id];
					remCur ^= h[e.id];
				}
			}
			writeln (mark);
			return mark;
		}

		writeln (equal (calc (a), calc (b)) ? "YES" : "NO");
	}
}

import std.algorithm;
import std.conv;
import std.random;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int n;
	while (readf !(" %s") (n) > 0)
	{
		rndGen.seed (1235);
		auto h = new ulong [n];
		foreach (ref c; h)
		{
			c = uniform (1, ulong.max);
		}

		alias Segment = Tuple !(int, q{lo}, int, q{hi});
		auto a = new Segment [n];
		auto b = new Segment [n];
		foreach (i; 0..n)
		{
			readf !(" %s %s %s %s")
			    (a[i].lo, a[i].hi, b[i].lo, b[i].hi);
		}
		long res = 0;

		alias Event = Tuple !(int, q{pos}, int, q{id});

		ulong [] calc (const ref Segment [] a)
		{
			Event [] events;
			foreach (i, const ref s; a)
			{
				events ~= Event (s.lo * 2 + 1, i.to !(int));
				events ~= Event (s.hi * 2 + 0, i.to !(int));
			}
			sort (events);

			auto mark = new ulong [n];
			auto rem = new ulong [n];
			ulong addCur = 0;
			ulong remCur = 0;
			foreach (const ref e; events)
			{
				bool isAdd = e.pos & 1;
				if (isAdd)
				{
					addCur ^= h[e.id];
					rem[e.id] = remCur;
				}
				else
				{
					mark[e.id] = addCur ^ rem[e.id];
					remCur ^= h[e.id];
				}
			}
			debug {writeln (mark);}
			return mark;
		}

		writeln (equal (calc (a), calc (b)) ? "YES" : "NO");
	}
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

void bChmax(T)(T[] bit, int pos, T val)
in {
  assert(0 <= pos && pos < bit.length, "bChmax: 0 <= pos < |bit| must hold");
}
do {
  for (int x = pos; x < bit.length; x |= x + 1) {
    chmax(bit[x], val);
  }
}

// max of [0, pos)
T bMax(T)(T[] bit, int pos)
in {
  assert(0 <= pos && pos <= bit.length, "bMax: 0 <= pos <= |bit| must hold");
}
do {
  T ret = -1;
  for (int x = pos - 1; x >= 0; x = (x & (x + 1)) - 1) {
    chmax(ret, bit[x]);
  }
  return ret;
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      auto SA = new long[N];
      auto TA = new long[N];
      auto SB = new long[N];
      auto TB = new long[N];
      foreach (i; 0 .. N) {
        SA[i] = readLong();
        TA[i] = readLong();
        SB[i] = readLong();
        TB[i] = readLong();
      }

      bool ans = true;
      foreach (phase; 0 .. 2) {
        auto xs = SA.dup ~ TA.dup ~ SB.dup ~ TB.dup;
        xs = xs.sort.uniq.array;
        const xsLen = cast(int)(xs.length);

        auto lecsSA = iota(N).array;
        auto lecsTA = iota(N).array;
        lecsSA.sort!((i, j) => (SA[i] < SA[j]));
        lecsTA.sort!((i, j) => (TA[i] < TA[j]));

        auto bit = new long[xsLen];
        bit[] = -1;
        int posI;
        foreach (j; lecsSA) {
          for (; posI < N && TA[lecsTA[posI]] < SA[j]; ++posI) {
            const i = lecsSA[posI];
            debug {
              writeln("add i = ", i);
            }
            const key = xs.lowerBound(SB[i]);
            bit.bChmax(key, TB[i]);
          }
          {
            debug {
              writeln("check j = ", j);
            }
            const key = xs.lowerBound(TB[j]);
            const res = bit.bMax(key + 1);
            if (res >= SB[j]) {
              debug {
                writefln("found j = %s, res = %s", j, res);
              }
              ans = false;
            }
          }
        }

        swap(SA, SB);
        swap(TA, TB);
      }
      writeln(ans ? "YES" : "NO");
    }
  } catch (EOFException e) {
  }
}


import std;

void main(){
	int t=readln().strip.to!int;
	foreach(_;0..t){
		readln();
		auto a=readln.strip.split.to!(int[]);
		writeln(min(2,a.map!(x=>x==0).group.filter!(x=>!x[0]).walkLength));
	}
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void solve()
{
    readln;
    auto ans = readln.splitter
        .map!(to!int)
        .chunkBy!(x => x != 0)
        .count!(x => x[0] != 0);

    .writeln(min(2, ans));
}

void main()
{
    size_t TC = 1;
    TC = readln.strip.to!int;
    foreach (_; 0 .. TC)
        solve();
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

void main() {
  try {
    for (; ; ) {
      const numCases = readInt;
      foreach (caseId; 0 .. numCases) {
        const N = readInt;
        auto A = new long[N];
        foreach (i; 0 .. N) {
          A[i] = readLong;
        }

        long ans;
        for (int i = 0, j; i < N; i = j) {
          for (j = i; j < N && (A[i] != 0) == (A[j] != 0); ++j) {}
          if (A[i] != 0) {
            ++ans;
          }
        }
        chmin(ans, 2);
        writeln(ans);
      }
    }
  } catch (EOFException e) {
  }
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void solve()
{
    readln;
    readln.splitter
        .map!(to!int)
        .chunkBy!(x => x != 0)
        .count!(x=> x[0] != 0)
        .writeln();
}

void main()
{
    size_t TC = 1;
    TC = readln.strip.to!int;
    foreach (_; 0 .. TC)
        solve();
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

void main() {
  try {
    for (; ; ) {
      const numCases = readInt;
      foreach (caseId; 0 .. numCases) {
        const N = readInt;
        auto A = new long[N];
        foreach (i; 0 .. N) {
          A[i] = readLong;
        }

        long ans;
        for (int i = 0, j; i < N; i = j) {
          for (j = i; j < N && (A[i] != 0) == (A[j] != 0); ++j) {}
          if (A[i] != 0) {
            ++ans;
          }
        }
        writeln(ans);
      }
    }
  } catch (EOFException e) {
  }
}


import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;

void main() {
  auto s = readln.strip.split.map!(to!int).array;
  immutable h = s[0], w = s[1];
  auto a = new string[h];
  foreach (i; 0 .. h) {
    a[i] = readln.strip;
  }
  int c;
  foreach (i; 0 .. h) {
    foreach (j; 0 .. w) {
      if (a[i][j] == '*') ++c;
    }
  }
  bool test() {
    foreach (i; 0 .. h) {
      foreach (j; 0 .. w) {
        if (a[i][j] == '*') {
          int go (int di, int dj) {
            int x = i + di;
            int y = j + dj;
            int r;
            while (x >= 0 && x < h && y >= 0 && y < w && a[x][y] == '*') {
              ++r;
              x += di;
              y += dj;
            }
            return r;
          }
          auto e = new int[4];
          e[0] = go (0, 1);
          e[1] = go (0, -1);
          e[2] = go (1, 0);
          e[3] = go (-1, 0);
          if (e.minElement () > 0 && e.sum == c - 1) {
            return true;
          }
        }
      }
    }
    return false;
  }
  writeln (test() ? "YES" : "NO");
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int h = read.to!int;
	int w = read.to!int;

	bool[][] as;
	foreach(i; 0 .. h){
		as ~= readln.chomp.to!(char[]).map!(x => x == '*').array;
	}

	string ans = "YES";

	bool f = 0;
	int i0, j0;
	foreach(i; 1 .. h - 1) foreach(j; 1 .. w - 1){
		if(as[i][j] && as[i - 1][j] && as[i + 1][j] && as[i][j - 1] && as[i][j + 1]){
			if(f == 0) i0 = i, j0 = j, f = 1;
			else ans = "NO";
		}
	}
	if(f == 0) ans = "NO";

	if(ans == "NO"){
		ans.writeln;
		return;
	}

	int t, b, l, r;
	foreach_reverse(i; 0 .. i0) if(!as[i][j0]) break; else t = i;
	foreach(i; i0 + 1 .. h) if(!as[i][j0]) break; else b = i;
	foreach_reverse(j; 0 .. j0) if(!as[i0][j]) break; else l = j;
	foreach(j; j0 + 1 .. w) if(!as[i0][j]) break; else r = j;

	foreach(i; 0 .. h) foreach(j; 0 .. w){
		if(i != i0 && j != j0 && as[i][j]) ans = "NO";
		if(i == i0 && (j < l || j > r) && as[i][j]) ans = "NO";
		if(j == j0 && (i < t || i > b) && as[i][j]) ans = "NO";
	}

	ans.writeln;

}

/*
	bool ng = 0;
	int[] ls, rs, ts, bs;
	foreach(i; 0 .. h){
		int f = 0;
		int l = -1, r = -1;
		foreach(j; 0 .. w){
			if(as[i][j]){
				if(f == 0) f = 1, l = j;
				else if(f == 2) ng = 1;
			}
			else{
				if(f == 1) f = 2, r = j;
			}
		}
		ls ~= l, rs ~= r;
	}
	foreach(j; 0 .. w){
		int f = 0;
		int t = -1, b = -1;
		foreach(i; 0 .. h){
			if(as[i][j]){
				if(f == 0) f = 1, t = i;
				else if(f == 2) ng = 1;
			}
			else{
				if(f == 1) f = 2, b = i;
			}
		}
		ts ~= t, bs ~= b;
	}

*/

import std.stdio : writef, readf, readln, writeln, writefln;
import std.array : array, split;
import std.algorithm;
import std.conv : to;
import std.range;
import std.algorithm.comparison;
import std.container.rbtree : RBT = RedBlackTree;
import std.string ;
import core.memory : GC;
import std.typecons : tuple;
import std.math;

alias Tree = RBT!int;

void main() {
  GC.disable();

  //

  int h, w;
  readf(" %s %s\n", h, w);

  auto m = new string[h];

  int tt = 0;
  foreach(i; 0..h) {
    m[i] = readln.strip;
    foreach(e; m[i]) if (e=='*') tt++;
  }

  foreach(i; 1..h-1) {
    foreach(j; 1..w-1) {
    if (m[i][j] == '*'  && m[i-1][j] == '*'
        && m[i+1][j] == '*' && m[i][j+1] == '*'
        && m[i][j-1] == '*') {
      int k = j+1;
      while(k < w && m[i][k] == '*') { tt--; k++;}
      k = j-1;
      while(k >= 0 && m[i][k] == '*') { tt--; k--;}
      k = i-1;
      while(k >= 0 && m[k][j] == '*') { tt--; k--;}
      k = i+1;
      while(k < h && m[k][j] == '*') { tt--; k++;}

      tt--;

      if (tt == 0) {
        writeln("YES");
        return;
      } else {
        writeln("NO");
        return;
      }

    }
  }
  }

  writeln("NO");

}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static string[] s_rd;
T RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
string RDR()() { return readln.chomp; }
T[] ARR(T = long)(in string str, T fix = 0) { auto r = str.split.to!(T[]); r[] += fix; return r; }
size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
long lcm(long x, long y) { return x * y / gcd(x, y); }

long mod = 10^^9 + 7;
//long mod = 998244353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }

void main()
{
	auto h = RD!int;
	auto w = RD!int;
	auto s = new string[](h);
	foreach (i; 0..h)
	{
		s[i] = RD!string;
	}

	auto cnt_w = new long[](h);
	foreach (y; 0..h)
	{
		bool isStart;
		char last = '.';
		foreach (x; 0..w)
		{
			if (s[y][x] == '*')
			{
				if (last == '.')
				{
					if (!isStart)
					{
						isStart = true;
						cnt_w[y] = 1;
					}
					else
					{
						cnt_w[y] = -1;
						break;
					}
				}
				else
				{
					++cnt_w[y];
				}
			}
			last = s[y][x];
		}
	}

	auto cnt_h = new long[](w);
	foreach (x; 0..w)
	{
		bool isStart;
		char last = '.';
		foreach (y; 0..h)
		{
			if (s[y][x] == '*')
			{
				if (last == '.')
				{
					if (!isStart)
					{
						isStart = true;
						cnt_h[x] = 1;
					}
					else
					{
						cnt_h[x] = -1;
						break;
					}
				}
				else
				{
					++cnt_h[x];
				}
			}
			last = s[y][x];
		}
	}

	bool ans = true;
	auto index_w = cnt_w.MAKE_IDX!"a > b"();
	auto index_h = cnt_h.MAKE_IDX!"a > b"();
	auto pos_y   = index_w[0];
	auto pos_x   = index_h[0];
	if (cnt_w[pos_y] < 3)
		ans = false;
	foreach (y; index_w[1..$])
	{
		if (cnt_w[y] == 0) break;
		if (cnt_w[y] > 1)
			ans = false;
		if (s[y][pos_x] == '.')
			ans = false;
	}

	if (cnt_h[pos_x] < 3)
		ans = false;
	foreach (x; index_h[1..$])
	{
		if (cnt_h[x] == 0) break;
		if (cnt_h[x] > 1)
			ans = false;
		if (s[pos_y][x] == '.')
			ans = false;
	}

	if (ans)
	{
		if (pos_y == 0 || pos_y == h - 1)
			ans = false;
		if (pos_x == 0 || pos_x == w - 1)
			ans = false;

		if (ans)
		{
			if (s[pos_y][pos_x-1] != '*')
				ans = false;
			if (s[pos_y][pos_x+1] != '*')
				ans = false;
			if (s[pos_y-1][pos_x] != '*')
				ans = false;
			if (s[pos_y+1][pos_x] != '*')
				ans = false;
		}
	}

	writeln(ans ? "YES" : "NO");
	stdout.flush();
	debug readln();
}

import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;

void main() {
  auto s = readln.strip.split.map!(to!int).array;
  immutable h = s[0], w = s[1];
  auto a = new string[h];
  foreach (i; 0 .. h) {
    a[i] = readln.strip;
  }
  int c;
  foreach (i; 0 .. h) {
    foreach (j; 0 .. w) {
      if (a[i][j] == '*') ++c;
    }
  }
  bool test() {
    foreach (i; 0 .. h) {
      foreach (j; 0 .. w) {
        if (a[i][j] == '*') {
          int go (int di, int dj) {
            int x = i + di;
            int y = j + dj;
            int r;
            while (x >= 0 && x < h && y >= 0 && y < h && a[x][y] == '*') {
              ++r;
              x += di;
              y += dj;
            }
            return r;
          }
          auto e = new int[4];
          e[0] = go (0, 1);
          e[1] = go (0, -1);
          e[2] = go (1, 0);
          e[3] = go (-1, 0);
          if (e.minElement () > 0 && e.sum == c - 1) {
            return true;
          }
        }
      }
    }
    return false;
  }
  writeln (test() ? "YES" : "NO");
}


import std.algorithm;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(real)).array;
		zip (a, a.drop (1)).map !(c => max (0,
		    to !(int) (abs (log2 (c[0] / c[1])) - 1E-9))).sum.writeln;
	}
}

import std.stdio, std.algorithm, std.conv, std.array, std.string, std.math, std.typecons, std.numeric, std.container, std.range;

void get(Args...)(ref Args args)
{
    import std.traits, std.meta, std.typecons;

    static if (Args.length == 1) {
        alias Arg = Args[0];

        static if (isArray!Arg) {
          static if (isSomeChar!(ElementType!Arg)) {
            args[0] = readln.chomp.to!Arg;
          } else {
            args[0] = readln.split.to!Arg;
          }
        } else static if (isTuple!Arg) {
            auto input = readln.split;
            static foreach (i; 0..Fields!Arg.length) {
                args[0][i] = input[i].to!(Fields!Arg[i]);
            }
        } else {
            args[0] = readln.chomp.to!Arg;
        }
    } else {
        auto input = readln.split;
        assert(input.length == Args.length);

        static foreach (i; 0..Args.length) {
            args[i] = input[i].to!(Args[i]);
        }
    }
}

void get_lines(Args...)(size_t N, ref Args args)
{
    import std.traits, std.range;

    static foreach (i; 0..Args.length) {
        static assert(isArray!(Args[i]));
        args[i].length = N;
    }

    foreach (i; 0..N) {
        static if (Args.length == 1) {
            get(args[0][i]);
        } else {
            auto input = readln.split;
            static foreach (j; 0..Args.length) {
                args[j][i] = input[j].to!(ElementType!(Args[j]));
            }
        }
    }
}

void main()
{
    int T; get(T); while (T--) {
        int N; get(N);
        int[] AA; get(AA);
        int c;
        foreach (i; 0..N-1) {
            auto a = AA[i];
            auto b = AA[i+1];
            if (a > b) swap(a, b);
            while (a * 2 < b) {
                ++c;
                a *= 2;
            }
        }
        writeln(c);
    }
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }

//long mod = 10^^9 + 7;
long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto t = RD!int;
	auto ans = new int[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto a = RDA;

		foreach (i; 0..n-1)
		{
			auto x = min(a[i], a[i+1]) * 2;
			auto y = max(a[i], a[i+1]);
			while (x < y)
			{
				++ans[ti];
				x *= 2;
			}
		}
	}

	foreach (e; ans)
		writeln(e);
	stdout.flush;
	debug readln;
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(int)).array;
		int res = 0;
		foreach (i; 0..n - 1)
		{
			auto b = a[i..i + 2].dup;
			sort (b);
			while (b[0] * 2 < b[1])
			{
				b[0] *= 2;
				res += 1;
			}
		}
		writeln (res);
	}
}


import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(int)).array;
		auto v = (a.sum % 2 == 0 && (a.sum % 4 == 0 || a.canFind (1)));
		writeln (v ? "Yes" : "No");
	}
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto t = RD!int;
	auto ans = new bool[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto a = RDA;

		long x, y;
		foreach (i; 0..n)
		{
			if (a[i] == 1)
				++x;
			else
				++y;
		}

		if (x % 2) continue;
		if (n % 2)
		{
			if (x < 2) continue;
		}
		ans[ti] = true;
	}

	foreach (e; ans)
		writeln(e ? "YES" : "NO");
	stdout.flush;
	debug readln;
}