#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define int long long
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

struct Rec {
  int l, d, r, u;
  friend ostream& operator<<(ostream& out, Rec R) {
    return out<<"("<<R.l<<" - "<<R.r<<") x ("<<R.d<<" - "<<R.u<<")";
  }
};

const int N = 1e9 + 5;
int MinU(vector<Rec>& recs) {
  int minu = N;
  for (auto& rec : recs) {
    mini(minu, rec.u);
  }
  return minu;
}
int MinR(vector<Rec>& recs) {
  int minr = N;
  for (auto& rec : recs) {
    mini(minr, rec.r);
  }
  return minr;
}
int MaxL(vector<Rec>& recs) {
  int maxl = 0;
  for (auto& rec : recs) {
    maxi(maxl, rec.l);
  }
  return maxl;
}
int MaxD(vector<Rec>& recs) {
  int maxd = 0;
  for (auto& rec : recs) {
    maxi(maxd, rec.d);
  }
  return maxd;
}
bool Between(int a, int b, int c) {
  return b <= a && a <= c;
}
VPII Go(int k, vector<Rec> recs, VPII sticks) {
  if (recs.empty()) {
    return sticks;
  }
  int minr = MinR(recs);
  int maxl = MaxL(recs);
  int minu = MinU(recs);
  int maxd = MaxD(recs);
  //debug(minr, maxl, minu, maxd);
  if (k == 1) {
    if (maxl > minr || maxd > minu) {
      return {};
    } else {
      sticks.PB({minr, minu});
      return sticks;
    }
  }
  VPII cands{{minr, minu},
             {minr, maxd},
             {maxl, maxd},
             {maxl, minu}};
  for (auto cand : cands) {
    vector<Rec> rems;
    sticks.PB(cand);
    for (auto rec : recs) {
      if (Between(cand.st, rec.l, rec.r) && Between(cand.nd, rec.d, rec.u)) {
      } else {
        rems.PB(rec);
      }
    }
    //debug(cand, rems);
    auto ret = Go(k - 1, rems, sticks);
    if (ret.empty()) {
      sticks.pop_back();
      continue;
    }
    return ret;
  }
  return {};
}
const PII bad{-1, -1};
const int kInf = 1e9;
PII Intersect(PII L, PII R) {
  if (L.nd < R.st || R.nd < L.st) { return bad; }
  return {max(L.st, R.st), min(L.nd, R.nd)};
}
void SelfIntersect(PII& L, PII R) {
  L = Intersect(L, R);
}
bool In(int d, PII p) {
  return Between(d, p.st, p.nd);
}
int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;
  
  int n, k;
  cin>>n>>k;
  vector<Rec> recs;
  map<int, int> mapuj;
  RE (i, n) {
    int l, d, r, u;
    cin>>l>>d>>r>>u;
    recs.PB({l, d, r, u});
    mapuj[l];
    mapuj[r];
    mapuj[d];
    mapuj[u];
  }
  int cnt = 0;
  map<int, int> inv;
  for (auto& p : mapuj) {
    cnt++;
    p.nd = cnt;
    inv[cnt] = p.st;
  }
  for (auto& rec : recs) {
    rec.l = mapuj[rec.l];
    rec.r = mapuj[rec.r];
    rec.d = mapuj[rec.d];
    rec.u = mapuj[rec.u];
  }
  auto ret = Go(k, recs, {});
  if (!ret.empty()) {
    while (SZ(ret) < k) {
      ret.PB(ret.back());
    }
    for (auto cand : ret) {
      cout<<inv[cand.st]<<" "<<inv[cand.nd]<<endl;
    }
    return 0;
  }
  debug("hard");
  assert(k == 4);
  
  int minr = MinR(recs);
  int maxl = MaxL(recs);
  int minu = MinU(recs);
  int maxd = MaxD(recs);
  PII intv_l = {minu + 1, maxd - 1};
  PII intv_r = intv_l;
  PII intv_u = {minr + 1, maxl - 1};
  PII intv_d = intv_u;
  
  PII all = {0, kInf};
  VPII up_to_du(cnt + 2, all);
  VPII from_du(cnt + 2, all);
  VPII up_to_lr(cnt + 2, all);
  VPII from_lr(cnt + 2, all);
  
  VI up_to_r(cnt + 2, cnt); // najmniejsze ograniczenie na dolny_x
  VI from_r(cnt + 2, cnt); // najmniejsze ograniczene na gorny_x
  VI from_u(cnt + 2, cnt); // najmniejsze ograniczenie na prawy_y
  VI from_d(cnt + 2, 0); // najwieksze ograniczenie na prawy_y
  
  int minRhor = cnt;
  for (auto rec : recs) {
    int reachR = rec.l <= minr;
    int reachL = rec.r >= maxl;
    int reachU = rec.d <= minu;
    int reachD = rec.u >= maxd;
    int sum = reachR + reachL + reachU + reachD;
    assert(sum);
    if (sum >= 3) { continue; }
    if (sum == 1) {
      if (reachR) {
        SelfIntersect(intv_r, {rec.d, rec.u});
      } else if (reachL) {
        SelfIntersect(intv_l, {rec.d, rec.u});
      } else if (reachD) {
        SelfIntersect(intv_d, {rec.l, rec.r});
      } else {
        SelfIntersect(intv_u, {rec.l, rec.r});
      }
    } else {
      if (reachR && reachL) {
        SelfIntersect(up_to_lr[rec.u], {rec.d, rec.u});
        SelfIntersect(from_lr[rec.d], {rec.d, rec.u});
      } else if (reachU && reachD) {
        SelfIntersect(up_to_du[rec.r], {rec.l, rec.r});
        SelfIntersect(from_du[rec.l], {rec.l, rec.r});
        mini(minRhor, rec.r); 
      } else if (reachR && reachU) {
        mini(up_to_r[rec.u], rec.r);
      } else if (reachU && reachL) {
        mini(from_u[rec.l], rec.u);
      } else if (reachL && reachD) {
        maxi(from_d[rec.l], rec.d);
      } else if (reachD && reachR) {
        mini(from_r[rec.d], rec.r);
      }
    }
  }
  RE (i, cnt) {
    SelfIntersect(up_to_lr[i], up_to_lr[i - 1]);
    SelfIntersect(up_to_du[i], up_to_du[i - 1]);
    mini(up_to_r[i], up_to_r[i - 1]);
  }
  FORD (i, cnt, 1) {
    SelfIntersect(from_lr[i], from_lr[i + 1]);
    SelfIntersect(from_du[i], from_du[i + 1]);
    mini(from_r[i], from_r[i + 1]);
    mini(from_u[i], from_u[i + 1]);
    maxi(from_d[i], from_d[i + 1]);
  }
  
  REP (tr, 2) { // tr == 0 ->  dolny_x < gorny_x
    FOR (lewy_y, intv_r.st, intv_r.nd) {
      int dolny_x, gorny_x;
      if (tr == 0) {
        dolny_x = min({intv_u.nd, minRhor, up_to_r[lewy_y - 1]});
        if (dolny_x == -1) { continue; }
        if (!In(dolny_x, intv_u)) { continue; }
        PII hors = Intersect(intv_d, from_du[dolny_x + 1]);
        gorny_x = min({hors.nd, from_r[lewy_y + 1]});
        if (gorny_x == -1) { continue; }
        if (!In(gorny_x, hors)) { continue; }
      } else {
        gorny_x = min({intv_d.nd, minRhor, from_r[lewy_y + 1]});
        if (gorny_x == -1) { continue; }
        if (!In(gorny_x, intv_d)) { continue; }
        PII hors = Intersect(intv_u, from_du[gorny_x + 1]);
        dolny_x = min(hors.nd, up_to_r[lewy_y - 1]);
        if (dolny_x == -1) { continue; }
        if (!In(dolny_x, hors)) { continue; }
      }
      PII at_prawy = intv_l;
      SelfIntersect(at_prawy, {from_d[gorny_x + 1], cnt});
      SelfIntersect(at_prawy, up_to_lr[lewy_y - 1]);
      SelfIntersect(at_prawy, from_lr[lewy_y + 1]);
      SelfIntersect(at_prawy, {0, from_u[dolny_x + 1]});
      if (at_prawy.nd == -1) { continue; }
      VPII sol{{minr, lewy_y}, {dolny_x, minu}, {gorny_x, maxd}, {maxl, at_prawy.nd}};
      for (auto stick : sol) {
        cout<<inv[stick.st]<<" "<<inv[stick.nd]<<endl;
      }
      for (auto rec : recs) {
        int ok = 0;
        for (auto stick : sol) {
          if (Between(stick.st, rec.l, rec.r) && Between(stick.nd, rec.d, rec.u)) {
            ok = 1;
          }
        }
        assert(ok);
      }
      return 0;
    }
  }
  assert(false);

  
  return 0;
}
