#include <algorithm>     #include <iostream>     #include <sstream>     #include <string>     #include <vector>     #include <queue>     #include <set>     #include <map>     #include <cstdio>     #include <cstdlib>     #include <cctype>     #include <cmath>     #include <cstring>   #include <list>     #include <cassert>   #include <climits>   #include <bitset>   #include <chrono>   #include <random>   using namespace std;      #define PB push_back     #define MP make_pair     #define SZ(v) ((int)(v).size())     #define FOR(i,a,b) for(int i=(a);i<(b);++i)     #define REP(i,n) FOR(i,0,n)     #define FORE(i,a,b) for(int i=(a);i<=(b);++i)     #define REPE(i,n) FORE(i,0,n)     #define FORSZ(i,a,v) FOR(i,a,SZ(v))     #define REPSZ(i,v) REP(i,SZ(v))     std::mt19937 rnd((int)std::chrono::steady_clock::now().time_since_epoch().count());   typedef long long ll;   ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }      template<typename Item, typename Sum, typename Lazy> struct SplayTree {    struct Node { int par, ch[2]; Item item; Sum sum; Lazy lazy; Node(Item item, Sum sum, Lazy lazy) :par(-1), item(item), sum(sum), lazy(lazy) { ch[0] = ch[1] = -1; } };    vector<Node> nodes;       void reset() { nodes.clear(); }    void apply(int x, Lazy lazy) { nodes[x].item += lazy; nodes[x].sum += lazy; nodes[x].lazy += lazy; }    void push(int x) { REP(z, 2) if (nodes[x].ch[z] != -1) apply(nodes[x].ch[z], nodes[x].lazy); nodes[x].lazy = Lazy(); }    void update(int x) { nodes[x].sum = Sum(); if (nodes[x].ch[0] != -1) nodes[x].sum += nodes[nodes[x].ch[0]].sum; nodes[x].sum += Sum(nodes[x].item); if (nodes[x].ch[1] != -1) nodes[x].sum += nodes[nodes[x].ch[1]].sum; }    void connect(int x, int p, int z) { if (x != -1) nodes[x].par = p; if (p != -1) nodes[p].ch[z] = x; }    int disconnect(int p, int z) { int x = nodes[p].ch[z]; nodes[p].ch[z] = -1; if (x != -1) nodes[x].par = -1; return x; }    void rotate(int x) {     int p = nodes[x].par, g = nodes[p].par, z = nodes[p].ch[0] == x ? 0 : 1, y = nodes[x].ch[1 - z]; push(p), push(x);     connect(y, p, z), connect(p, x, 1 - z), connect(x, g, g == -1 ? -1 : nodes[g].ch[0] == p ? 0 : 1); update(p);    }    void splay(int x, int y = -1) { if (nodes[x].par == y) return; while (nodes[x].par != y) { int p = nodes[x].par, g = nodes[p].par; if (g != y) rotate((nodes[p].ch[0] == x) == (nodes[g].ch[0] == p) ? p : x); rotate(x); } update(x); }    int first(int x) { if (x == -1) return x; splay(x); while (nodes[x].ch[0] != -1) x = nodes[x].ch[0]; splay(x); return x; }    int last(int x) { if (x == -1) return x; splay(x); while (nodes[x].ch[1] != -1) x = nodes[x].ch[1]; splay(x); return x; }       int add(Item item) { nodes.PB(Node(item, Sum(item), Lazy())); return SZ(nodes) - 1; };    int join(int l, int r) { if (l == -1) return r; l = last(l); push(l); connect(r, l, 1); update(l); return l; }    void split(int x, int v, int& l, int& r) {     if (x == -1) { l = r = -1; return; } else splay(x);     l = r = -1;     while (x != -1) { push(x); if (nodes[x].item.l() < v) l = x, x = nodes[x].ch[1]; else r = x, x = nodes[x].ch[0]; }     if (l != -1) splay(l); if (r != -1) splay(r, l);     if (l == -1) return;     assert(nodes[l].par == -1 && nodes[l].ch[1] == r && (r == -1 || nodes[r].ch[0] == -1));     push(l); disconnect(l, 1); update(l);     if (nodes[l].item.r() < v) return;     Item splitted = nodes[l].item.split(v);     if (nodes[l].ch[0] != -1 && nodes[nodes[l].ch[0]].item.r() == nodes[l].item.r()) l = disconnect(l, 0);     if (r == -1 || splitted.l() != nodes[r].item.l()) r = join(add(splitted), r);     update(l);    }    void gather(int x, vector<Item>& ret) { push(x); if (nodes[x].ch[0] != -1) gather(nodes[x].ch[0], ret); ret.PB(nodes[x].item); if (nodes[x].ch[1] != -1) gather(nodes[x].ch[1], ret); }    vector<Item> all(int x) { vector<Item> ret; if (x != -1) splay(x), gather(x, ret); return ret; }   };      const int MAXRECT = 200000;   const int INF = 1000000000;   struct Rect { int lt, rt, lx, rx; };      int nrect, sx;   Rect rect[MAXRECT];      struct Line {    int ly, ry, lcost, slope;    Line() {}    Line(int ly, int ry, int lcost, int slope) :ly(ly), ry(ry), lcost(lcost), slope(ly == ry ? 0 : slope) {}    int rcost() { return lcost + slope * (ry - ly); }    int len() { return ry - ly; }    void setly(int nly) { lcost += (nly - ly) * slope; ly = nly; if (ly == ry) slope = 0; }    void setry(int nry) { ry = nry; if (ly == ry) slope = 0; }    int l() { return ly; }    int r() { return ry; }    Line split(int y) {     assert(ly < y && y <= ry);     auto ret = Line(y, ry, lcost + (y - ly) * slope, slope);     setry(y - 1);     return ret;    }   };   struct SumLine { SumLine() {} SumLine(Line line) {} };   SumLine& operator+=(SumLine& a, const SumLine& b) { return a; }   struct LazyLine {};   Line& operator+=(Line& a, const LazyLine& b) { return a; }   SumLine& operator+=(SumLine& a, const LazyLine& b) { return a; }   LazyLine& operator+=(LazyLine& a, const LazyLine& b) { return a; }      SplayTree<Line, SumLine, LazyLine> linetree;      void printfunc(int lineroot,int tline) {    if (lineroot == -1) {     printf(  BLOCKED );    } else {     auto alllines = linetree.all(lineroot);     for (auto line : alllines) printf(  (%d,%d)..(%d,%d) , line.ly == -INF ? -INF : line.ly + tline, line.ly == -INF ? INF : line.lcost, line.ry == +INF ? +INF : line.ry + tline, line.ry == +INF ? INF : line.rcost());    }    puts(  );   }      int t;      int rtrimfunc(int node, int nry) {    while(true) {     node = linetree.last(node);     if (linetree.nodes[node].item.ry <= nry) break;     if (linetree.nodes[node].item.ly < nry || linetree.nodes[node].item.ly == nry && linetree.nodes[node].ch[0] == -1) {      linetree.nodes[node].item.setry(nry);      break;     }     node = linetree.disconnect(node, 0);     assert(node != -1);    }    return node;   }   int lgrowfunc(int node, int nly) {    node = linetree.first(node);    assert(nly <= linetree.nodes[node].item.ly);    if (nly == linetree.nodes[node].item.ly) return node;    if (linetree.nodes[node].item.slope == -1 || linetree.nodes[node].item.ly == linetree.nodes[node].item.ry) {     linetree.nodes[node].item.slope = -1;     linetree.nodes[node].item.setly(nly);     linetree.update(node);    } else {     Line line(nly, linetree.nodes[node].item.ly, linetree.nodes[node].item.lcost + linetree.nodes[node].item.ly - nly, -1);     node = linetree.join(linetree.add(line), node);    }    return node;   }   int rgrowfunc(int node, int nry) {    node = linetree.last(node);    assert(nry >= linetree.nodes[node].item.ry);    if (nry == linetree.nodes[node].item.ry) return node;    if (linetree.nodes[node].item.slope == +1 || linetree.nodes[node].item.ly == linetree.nodes[node].item.ry) {     linetree.nodes[node].item.slope = +1;     linetree.nodes[node].item.setry(nry);     linetree.update(node);    } else {     Line line(linetree.nodes[node].item.ry, nry, linetree.nodes[node].item.rcost(), +1);     node = linetree.join(node, linetree.add(line));    }    return node;   }   int shiftfunc(int node, int dt) {    if (dt == 0) return node;    node = linetree.first(node);    int ply = linetree.nodes[node].item.ly;    if (ply != -INF) node = lgrowfunc(node, ply - dt);    node = linetree.last(node);    int pry = linetree.nodes[node].item.ry;    if (pry != +INF) node = rtrimfunc(node, pry - dt);    return node;   }   int mergefunc(int l, int r) {    //printf( merging n );    //printfunc(l, t);    //printfunc(r, t);    l = linetree.last(l);    r = linetree.first(r);    while (l != -1 && r != -1 && linetree.nodes[l].item.rcost() > linetree.nodes[r].item.lcost) {     assert(linetree.nodes[l].item.ry == linetree.nodes[r].item.ly);     if (linetree.nodes[l].item.slope == -1 || linetree.nodes[l].item.ly == linetree.nodes[l].item.ry) {      r = lgrowfunc(r, linetree.nodes[l].item.ly);      l = linetree.disconnect(l, 0);     } else {      assert(linetree.nodes[l].item.slope == 1);      if (linetree.nodes[r].item.lcost + linetree.nodes[l].item.len() <= linetree.nodes[l].item.lcost) {       r = lgrowfunc(r, linetree.nodes[l].item.ly);       l = linetree.disconnect(l, 0);      } else {       int y = linetree.nodes[r].item.lcost - linetree.nodes[l].item.lcost + linetree.nodes[l].item.ly + linetree.nodes[l].item.ry; assert(y % 2 == 0); y /= 2;       assert(y > linetree.nodes[l].item.ly && y < linetree.nodes[l].item.ry);       r = lgrowfunc(r, y);       linetree.nodes[l].item.setry(y);      }     }     l = linetree.last(l);     r = linetree.first(r);    }    while (l != -1 && r != -1 && linetree.nodes[l].item.rcost() < linetree.nodes[r].item.lcost) {     assert(linetree.nodes[l].item.ry == linetree.nodes[r].item.ly);     if (linetree.nodes[r].item.slope == +1 || linetree.nodes[r].item.ly == linetree.nodes[r].item.ry) {      l = rgrowfunc(l, linetree.nodes[r].item.ry);      r = linetree.disconnect(r, 1);     } else {      assert(linetree.nodes[r].item.slope == -1);      if (linetree.nodes[l].item.rcost() + linetree.nodes[r].item.len() <= linetree.nodes[r].item.rcost()) {       l = rgrowfunc(l, linetree.nodes[r].item.ry);       r = linetree.disconnect(r, 1);      } else {       int y = linetree.nodes[r].item.rcost() - linetree.nodes[l].item.rcost() + linetree.nodes[r].item.ly + linetree.nodes[r].item.ry; assert(y % 2 == 0); y /= 2;       assert(y > linetree.nodes[r].item.ly && y < linetree.nodes[r].item.ry);       l = rgrowfunc(l, y);       linetree.nodes[r].item.setly(y);      }     }     l = linetree.last(l);     r = linetree.first(r);    }    int ret = linetree.join(l, r);    //printf( ->  ); printfunc(ret, t);    return ret;   }      struct Region {    int lx, rx, blockcnt, lineroot, tline;    Region(int lx, int rx, int blockcnt, int lineroot, int tline) :lx(lx), rx(rx), blockcnt(blockcnt), lineroot(lineroot), tline(tline) {};    int l() { return lx; }    int r() { return rx; }    void norm() { if (lineroot != -1) { lineroot = shiftfunc(lineroot, t - tline); tline = t; } }    Region split(int x) {     assert(lx < x && x <= rx);      norm();     auto ret = Region(x, rx, blockcnt, -1, tline);     rx = x - 1;     if (lineroot != -1) linetree.split(lineroot, x - t, lineroot, ret.lineroot);     return ret;    };   };   struct SumRegion {    int mnblockcnt;    SumRegion() { mnblockcnt = INT_MAX; }    SumRegion(Region region) { mnblockcnt = region.lineroot == -1 ? INT_MAX : region.blockcnt; }   };   SumRegion& operator+=(SumRegion& a, const SumRegion& b) { a.mnblockcnt = min(a.mnblockcnt, b.mnblockcnt); return a; }   struct LazyRegion {    int lazyblockcnt;    LazyRegion() { lazyblockcnt = 0; }    LazyRegion(int lazyblockcnt) :lazyblockcnt(lazyblockcnt) {}   };   Region& operator+=(Region& a, const LazyRegion& b) { a.blockcnt += b.lazyblockcnt; return a; }   SumRegion& operator+=(SumRegion& a, const LazyRegion& b) { if (a.mnblockcnt != INT_MAX) a.mnblockcnt += b.lazyblockcnt; return a; }   LazyRegion& operator+=(LazyRegion& a, const LazyRegion& b) { a.lazyblockcnt += b.lazyblockcnt; return a; }         SplayTree<Region, SumRegion, LazyRegion> regiontree;      void print(int regionroot) {    auto allregions = regiontree.all(regionroot);    for (auto region : allregions) {     //region.norm();     printf( [%d..%d] = %d: , region.lx, region.rx, region.blockcnt); if (region.lineroot!=-1 && region.tline != t) printf(  (delay %d) , t - region.tline);     printfunc(region.lineroot, region.tline);    }   }      int killzeroes(int node) {    regiontree.splay(node);    while (regiontree.nodes[node].sum.mnblockcnt == 0) {     //printf( killing n ); print(node);     while (regiontree.nodes[node].item.blockcnt != 0 || regiontree.nodes[node].item.lineroot == -1) {      //printf( node=%d n , node);      if (regiontree.nodes[node].ch[0] != -1 && regiontree.nodes[regiontree.nodes[node].ch[0]].sum.mnblockcnt == 0) {       node = regiontree.nodes[node].ch[0];      } else {       node = regiontree.nodes[node].ch[1];      }      assert(node != -1 && regiontree.nodes[node].sum.mnblockcnt == 0);     }     //printf( found node=%d n , node);     assert(regiontree.nodes[node].item.lineroot != -1);     regiontree.splay(node);     regiontree.nodes[node].item.lineroot = -1;     regiontree.update(node);    }    return node;   }      int rgrow(int node, int x) {    int l, r; regiontree.split(node, x + 1, l, r);    l = regiontree.last(l);    r = regiontree.first(r);    //printf( growing n );    //printf( l n ); print(l);    //printf( r n ); print(r);    if (l == -1 || regiontree.nodes[l].item.lineroot == -1) return regiontree.join(l, r);    while (r != -1 && regiontree.nodes[r].item.lineroot == -1 && regiontree.nodes[r].item.blockcnt == 0) {     //printf( step n );     assert(regiontree.nodes[l].item.rx + 1 == regiontree.nodes[r].item.lx);     regiontree.nodes[l].item.rx = regiontree.nodes[r].item.rx;     r = regiontree.disconnect(r, 1);     r = regiontree.first(r);    }    if (r != -1 && regiontree.nodes[r].item.lineroot != -1) {     assert(regiontree.nodes[l].item.rx + 1 == regiontree.nodes[r].item.lx);     regiontree.nodes[l].item.rx = regiontree.nodes[r].item.lx;     regiontree.nodes[l].item.norm();     regiontree.nodes[l].item.lineroot = rgrowfunc(regiontree.nodes[l].item.lineroot, regiontree.nodes[l].item.rx - t);     regiontree.nodes[r].item.norm();     regiontree.nodes[l].item.lineroot = mergefunc(regiontree.nodes[l].item.lineroot, regiontree.nodes[r].item.lineroot);     regiontree.nodes[l].item.rx = regiontree.nodes[r].item.rx;     r = regiontree.disconnect(r, 1);    } else {     regiontree.nodes[l].item.norm();     regiontree.nodes[l].item.lineroot = rgrowfunc(regiontree.nodes[l].item.lineroot, regiontree.nodes[l].item.rx - t);    }    int ret = regiontree.join(l, r);    //printf( after rgrow n ); print(ret);    return ret;   }      int lgrow(int node, int x) {    //printf( lgrow %d n , x);    int l, r; regiontree.split(node, x, l, r);    l = regiontree.last(l);    r = regiontree.first(r);    if (r == -1 || regiontree.nodes[r].item.lineroot == -1) return regiontree.join(l, r);    while (l != -1 && regiontree.nodes[l].item.lineroot == -1 && regiontree.nodes[l].item.blockcnt == 0) {     assert(regiontree.nodes[l].item.rx + 1 == regiontree.nodes[r].item.lx);     regiontree.nodes[r].item.lx = regiontree.nodes[l].item.lx;     l = regiontree.disconnect(l, 0);     l = regiontree.last(l);    }    if (l != -1 && regiontree.nodes[l].item.lineroot != -1) {     assert(regiontree.nodes[l].item.rx + 1 == regiontree.nodes[r].item.lx);     regiontree.nodes[l].item.rx = regiontree.nodes[r].item.lx;     regiontree.nodes[l].item.norm();     regiontree.nodes[l].item.lineroot = rgrowfunc(regiontree.nodes[l].item.lineroot, regiontree.nodes[l].item.rx - t);     regiontree.nodes[r].item.norm();     regiontree.nodes[l].item.lineroot = mergefunc(regiontree.nodes[l].item.lineroot, regiontree.nodes[r].item.lineroot);     regiontree.nodes[l].item.rx = regiontree.nodes[r].item.rx;     r = regiontree.disconnect(r, 1);    } else {     regiontree.nodes[r].item.norm();     regiontree.nodes[r].item.lineroot = lgrowfunc(regiontree.nodes[r].item.lineroot, regiontree.nodes[r].item.lx - t);    }    return regiontree.join(l, r);   }      int solve() {    //REP(i, nrect) printf( t=%d..%d y=%d..%d to %d..%d n , rect[i].lt, rect[i].rt, rect[i].lx - rect[i].lt, rect[i].rx - rect[i].lt, rect[i].lx - rect[i].rt, rect[i].rx - rect[i].rt);       linetree.reset();    regiontree.reset();    int linedn = linetree.add(Line(-INF, sx, abs(-INF - sx), -1));    int lineup = linetree.add(Line(sx, +INF, 0, +1));    int lineroot = linetree.join(linedn, lineup);    int regionroot = regiontree.add(Region(-INF, +INF, 0, lineroot, 0));       vector<pair<int, int>> e;    REP(i, nrect) e.PB(MP(2 * rect[i].lt + 1, i)), e.PB(MP(2 * rect[i].rt + 0, i));    sort(e.begin(), e.end());    //printf( INITIAL n ); print(regionroot);    REPSZ(i, e) {     t = e[i].first >> 1; int kind = e[i].first & 1, idx = e[i].second;     if (kind == 0) { // release rect      int l, m, r;      regiontree.split(regionroot, rect[idx].lx + 1, l, m);      regiontree.split(m, rect[idx].rx, m, r);      regiontree.apply(m, LazyRegion(-1));      regionroot = regiontree.join(regiontree.join(l, m), r);      regionroot = rgrow(regionroot, rect[idx].lx);      regionroot = lgrow(regionroot, rect[idx].rx);     }     if (kind == 1) { // block rect      int l, m, r;      regiontree.split(regionroot, rect[idx].lx + 1, l, m);      //printf( L n ); print(l);      //printf( M n ); print(m);      regiontree.split(m, rect[idx].rx, m, r);      //printf( M n ); print(m);      //printf( R n ); print(r);      m = killzeroes(m);      //printf( M n ); print(m);      regiontree.apply(m, LazyRegion(1));      regionroot = regiontree.join(regiontree.join(l, m), r);     }     //printf( after %s rect %d (t=%d) n , kind == 0 ?  releasing  :  blocking , idx + 1, t); print(regionroot);     //if (i == 0) exit(0);    }    //printf( FINAL (t=%d) n ,t); print(regionroot);       auto finalregions = regiontree.all(regionroot);    assert(SZ(finalregions) == 1);    auto finalregion = finalregions[0];    finalregion.norm();    assert(finalregion.lineroot != -1);    auto finalfunc = linetree.all(finalregion.lineroot);    int ret = INT_MAX;    for (auto func : finalfunc) ret = min(ret, min(func.lcost, func.rcost()));    return ret;   }      void run() {    scanf( %d , &nrect);    scanf( %d , &sx);    REP(i, nrect) scanf( %d%d%d%d , &rect[i].lt, &rect[i].rt, &rect[i].lx, &rect[i].rx), --rect[i].lt, ++rect[i].rt, --rect[i].lx, ++rect[i].rx;    printf( %d n , solve());   }      void stress() {    int mxrect = 100, mxdim = 100;    REP(rep, 10000) {     nrect = rnd() % mxrect + 1;     int tdim = rnd() % mxdim + 1;     int xdim = rnd() % mxdim + 1;     sx = rnd() % (xdim + 1);     REP(i, nrect) {      rect[i].lt = rnd() % tdim; rect[i].rt = rnd() % tdim; if (rect[i].lt > rect[i].rt) swap(rect[i].lt, rect[i].rt); rect[i].rt += 2;      rect[i].lx = rnd() % xdim; rect[i].rx = rnd() % xdim; if (rect[i].lx > rect[i].rx) swap(rect[i].lx, rect[i].rx); rect[i].rx += 2;     }     //printf( %d n%d n , nrect, sx); REP(i, nrect) printf( %d %d %d %d n , rect[i].lt + 1, rect[i].rt - 1, rect[i].lx + 1, rect[i].rx - 1);     solve();     printf( . );    }   }      int main() {    run();    //stress();    return 0;   }