#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m;
vector<int> a[N], e[N];
vector<bool> b[N];
int s[N];
set<int> bd;

int top = 0;

vector<int>::iterator st[N];

map<pair<int, int>, int> bm;

vector<int> p;
set<int> ps;

int fc[N];

void dfs0(int v, int f) {
  s[v] = 1;
  for (int u : e[v]) if (u != f && !bd.count(u)) {
    dfs0(u, v);
    s[v] += s[u];
  }
}

pair<int, int> dfs1(int v, int f, int os) {
  if (s[v] <= os) return {os, v};
  pair<int, int> ans = {N, v};
  int mo = os;
  for (int u : e[v]) if (u != f && !bd.count(u)) {
    mo = max(mo, s[u]);
    ans = min(ans, dfs1(u, v, os + s[v] - s[u]));
  }
  return min(ans, {mo, v});
}

void colr(int v, int cc) {
  //cerr << v << " bd=" << bd.size() << " c=" << cc << endl;
  dfs0(v, -1);
  int x = dfs1(v, -1, 0).second;
  //cerr << "  use " << x << " size=" << s[x] << "/" << s[v] << endl;
  fc[x] = cc;
  bd.insert(x);
  for (int y : e[x]) if (!bd.count(y))
    colr(y, cc + 1);
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    b[i].resize(a[i].size(), false);
  }

  for (int i = n - 1; i >= 0; --i) {
    for (int k = a[i].size() - 1; k >= 0; --k) if (!b[i][k]) {
      int j = a[i][k];
      b[i][k] = true;
      vector<int> p = {i};
      while (j != i) {
        int w = lower_bound(a[j].begin(), a[j].end(), p.back()) -
            a[j].begin();
        p.push_back(j);
        w = (w + 1) % a[j].size();
        b[j][w] = true;
        j = a[j][w];
      }
      if (p.size() == n) {
        if (m) continue;
        m = -1;
      }
      /*
      cerr << "New shape " << top << " size=" << p.size() << endl;
      if (p.size() < 10) {for (int x : p) cerr << x+1 << ", "; cerr << endl; }//*/

      for (int k = 0; k < p.size(); ++k) {
        int x = p[k], y = p[(k + 1)%p.size()];
        pair<int, int> pii = {min(x,y), max(x,y)};
        if (bm.count(pii)) {
          e[top].push_back(bm[pii]);
          e[bm[pii]].push_back(top);
          /*
          cerr << "edge " << top << " --- " << bm[pii] << endl; //*/
        } else bm[pii] = top;
      }

      ++top;
    }
  }

  colr(0, 1);

  for (int i = top - 1; i >= 0; --i) {
    printf("%d ", fc[i]);
  }
  puts("");
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m;
vector<int> a[N], e[N];

vector<int> s[N];

int top = 0;

vector<int>::iterator st[N];

map<pair<int, int>, int> bm;

vector<int> p;
set<int> ps;

int fc[N];

bool getnode(int from, int v) {
  if (v == from) {
    if (p.size() == n) return true;
    s[top] = p;

    for (int i = 0; i < p.size(); ++i) {
      int x = p[i], y = p[(i + 1) % p.size()];
      if (x > y) swap(x, y);
      pair<int, int> pii = {x, y};
      if (bm.count(pii)) {
        int z = bm[pii];
        e[z].push_back(top);
        e[top].push_back(z);
        // cerr << z << " -- " << top << endl;
      } else
        bm[pii] = top;
    }
    /*
        cerr << top << ": ";
        for (int x : s[top]) cerr << x << " ";
        cerr << endl;
    */
    ++top;
    return true;
  } else {
    p.push_back(v);
    ps.insert(v);
    auto it = a[v].begin();
    while (it != a[v].end()) {
      int k = *it;
      if (k >= 0 && k != p[p.size() - 2] && !ps.count(k)) {
        if (getnode(from, k)) {
          *it = -1;
          return true;
        }
      }
      ++it;
    }
    ps.erase(ps.find(v));
    p.pop_back();
  }
  return false;
}

void dfs0(int v, map<int, int>& s, int f, int bd) {
  s[v] = 1;
  for (int u : e[v])
    if (u != f && u != bd) {
      dfs0(u, s, v, bd);
      s[v] += s[u];
    }
}

int dfs1(int v, map<int, int>& s, int f, int bd, int zs) {
  if (s[v] <= zs) return -1;
  vector<int> nx;
  for (int u : e[v])
    if (u != f && u != bd) {
      nx.push_back(u);
    }
  sort(nx.begin(), nx.end(), [&](int x, int y) { return s[x] > s[y]; });
  for (int u : nx) {
    auto res = dfs1(u, s, v, bd, zs);
    if (res >= 0) return res;
  }
  return v;
}

void colr(int v, int bd, int cc) {
  map<int, int> s;

  dfs0(v, s, -1, bd);
  int zs = s[v] / 2;
  int x = dfs1(v, s, -1, bd, zs);
  fc[x] = cc;
  for (int y : e[x])
    if (y != bd) {
      colr(y, x, cc + 1);
    }
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    reverse(a[i].begin(), a[i].end());
  }
  for (int i = n - 1; i >= 0; --i) {
    auto it = a[i].begin();
    while (it != a[i].end()) {
      int j = *it;
      p = {i};
      ps = {};
      if (getnode(i, j)) {
        *it = -1;
      }
      ++it;
    }
  }

  colr(0, -1, 1);

  for (int i = top - 1; i >= 0; --i) {
    printf("%d ", fc[i]);
  }
  puts("");
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m;
vector<int> a[N], e[N];

vector<int> s[N];

int top = 0;

vector<int>::iterator st[N];

map<pair<int, int>, int> bm;

vector<int> p;
set<int> ps;

int fc[N];

bool getnode(int from, int v) {
  if (v == from) {
    if (p.size() == n) {
      if (m) return true;
      m = -1;
    }
    s[top] = p;

    for (int i = 0; i < p.size(); ++i) {
      int x = p[i], y = p[(i + 1) % p.size()];
      if (x > y) swap(x, y);
      pair<int, int> pii = {x, y};
      if (bm.count(pii)) {
        int z = bm[pii];
        e[z].push_back(top);
        e[top].push_back(z);
        // cerr << z << " -- " << top << endl;
      } else
        bm[pii] = top;
    }
    /*
        cerr << top << ": ";
        for (int x : s[top]) cerr << x << " ";
        cerr << endl;
    */
    ++top;
    return true;
  } else {
    p.push_back(v);
    ps.insert(v);
    auto it = a[v].begin();
    while (it != a[v].end()) {
      int k = *it;
      if (k >= 0 && k != p[p.size() - 2] && !ps.count(k)) {
        if (getnode(from, k)) {
          *it = -1;
          return true;
        }
      }
      ++it;
    }
    ps.erase(ps.find(v));
    p.pop_back();
  }
  return false;
}

void dfs0(int v, map<int, int>& s, int f, int bd) {
  s[v] = 1;
  for (int u : e[v])
    if (u != f && u != bd) {
      dfs0(u, s, v, bd);
      s[v] += s[u];
    }
}

int dfs1(int v, map<int, int>& s, int f, int bd, int zs) {
  if (s[v] <= zs) return -1;
  vector<int> nx;
  for (int u : e[v])
    if (u != f && u != bd) {
      nx.push_back(u);
    }
  sort(nx.begin(), nx.end(), [&](int x, int y) { return s[x] > s[y]; });
  for (int u : nx) {
    auto res = dfs1(u, s, v, bd, zs);
    if (res >= 0) return res;
  }
  return v;
}

void colr(int v, int bd, int cc) {
  map<int, int> s;

  dfs0(v, s, -1, bd);
  int zs = s[v] / 2;
  int x = dfs1(v, s, -1, bd, zs);
  fc[x] = cc;
  for (int y : e[x])
    if (y != bd) {
      colr(y, x, cc + 1);
    }
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    reverse(a[i].begin(), a[i].end());
  }
  for (int i = n - 1; i >= 0; --i) {
    auto it = a[i].begin();
    while (it != a[i].end()) {
      int j = *it;
      p = {i};
      ps = {};
      if (getnode(i, j)) {
        *it = -1;
      }
      ++it;
    }
  }

  colr(0, -1, 1);

  for (int i = top - 1; i >= 0; --i) {
    printf("%d ", fc[i]);
  }
  puts("");
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m;
vector<int> a[N], e[N];
vector<bool> b[N];

vector<int> s[N];

int top = 0;

vector<int>::iterator st[N];

map<pair<int, int>, int> bm;

vector<int> p;
set<int> ps;

int fc[N];

void dfs0(int v, map<int, int>& s, int f, int bd) {
  s[v] = 1;
  for (int u : e[v])
    if (u != f && u != bd) {
      dfs0(u, s, v, bd);
      s[v] += s[u];
    }
}

int dfs1(int v, map<int, int>& s, int f, int bd, int zs) {
  if (s[v] <= zs) return -1;
  vector<int> nx;
  for (int u : e[v])
    if (u != f && u != bd) {
      nx.push_back(u);
    }
  sort(nx.begin(), nx.end(), [&](int x, int y) { return s[x] > s[y]; });
  for (int u : nx) {
    auto res = dfs1(u, s, v, bd, zs);
    if (res >= 0) return res;
  }
  return v;
}

void colr(int v, int bd, int cc) {
  map<int, int> s;

  dfs0(v, s, -1, bd);
  int zs = s[v] / 2;
  int x = dfs1(v, s, -1, bd, zs);
  fc[x] = cc;
  for (int y : e[x])
    if (y != bd) {
      colr(y, x, cc + 1);
    }
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    b[i].resize(a[i].size(), false);
  }

  for (int i = n - 1; i >= 0; --i) {
    for (int k = a[i].size() - 1; k >= 0; --k) if (!b[i][k]) {
      int j = a[i][k];
      b[i][k] = true;
      vector<int> p = {i};
      while (j != i) {
        int w = lower_bound(a[j].begin(), a[j].end(), p.back()) -
            a[j].begin();
        p.push_back(j);
        w = (w + 1) % a[j].size();
        b[j][w] = true;
        j = a[j][w];
      }
      if (p.size() == n) {
        if (m) continue;
        m = -1;
      }
      /*
      cerr << "New shape " << top << endl;
      for (int x : p) cerr << x+1 << ", "; cerr << endl; //*/

      for (int k = 0; k < p.size(); ++k) {
        int x = p[k], y = p[(k + 1)%p.size()];
        pair<int, int> pii = {min(x,y), max(x,y)};
        if (bm.count(pii)) {
          e[top].push_back(bm[pii]);
          e[bm[pii]].push_back(top);
          /*
          cerr << "edge " << top << " --- " << bm[pii] << endl; //*/
        } else bm[pii] = top;
      }

      ++top;
    }
  }

  colr(0, -1, 1);

  for (int i = top - 1; i >= 0; --i) {
    printf("%d ", fc[i]);
  }
  puts("");
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m;
vector<int> a[N], e[N];
vector<bool> b[N];
map<int, int> s;
set<int> bd;

int top = 0;

vector<int>::iterator st[N];

map<pair<int, int>, int> bm;

vector<int> p;
set<int> ps;

int fc[N];

void dfs0(int v, int f) {
  s[v] = 1;
  for (int u : e[v]) if (u != f && !bd.count(u)) {
    dfs0(u, v);
    s[v] += s[u];
  }
}

int dfs1(int v, int f, int zs) {
  if (s[v] - 1 <= zs) return v;
  int ans = -1;
  for (int u : e[v]) if (u != f && !bd.count(u)) {
    auto res = dfs1(u, v, zs);
    if (ans < 0 || s[res] > s[ans])
      ans = res;
  }
  return ans;
}

void colr(int v, int cc) {
  //cerr << v << " bd=" << bd.size() << " c=" << cc << endl;
  s.clear();

  dfs0(v, -1);
  int x = dfs1(v, -1, s[v] / 2);
  //cerr << "  use " << x << " size=" << s[x] << "/" << s[v] << endl;
  fc[x] = cc;
  bd.insert(x);
  for (int y : e[x]) if (!bd.count(y))
    colr(y, cc + 1);
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    b[i].resize(a[i].size(), false);
  }

  for (int i = n - 1; i >= 0; --i) {
    for (int k = a[i].size() - 1; k >= 0; --k) if (!b[i][k]) {
      int j = a[i][k];
      b[i][k] = true;
      vector<int> p = {i};
      while (j != i) {
        int w = lower_bound(a[j].begin(), a[j].end(), p.back()) -
            a[j].begin();
        p.push_back(j);
        w = (w + 1) % a[j].size();
        b[j][w] = true;
        j = a[j][w];
      }
      if (p.size() == n) {
        if (m) continue;
        m = -1;
      }
      /*
      cerr << "New shape " << top << " size=" << p.size() << endl;
      if (p.size() < 10) {for (int x : p) cerr << x+1 << ", "; cerr << endl; }//*/

      for (int k = 0; k < p.size(); ++k) {
        int x = p[k], y = p[(k + 1)%p.size()];
        pair<int, int> pii = {min(x,y), max(x,y)};
        if (bm.count(pii)) {
          e[top].push_back(bm[pii]);
          e[bm[pii]].push_back(top);
          /*
          cerr << "edge " << top << " --- " << bm[pii] << endl; //*/
        } else bm[pii] = top;
      }

      ++top;
    }
  }

  colr(0, 1);

  for (int i = top - 1; i >= 0; --i) {
    printf("%d ", fc[i]);
  }
  puts("");
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int64_t N = 1e5 + 10;

int n, m, top;
vector<int> a[N], e[N];
vector<bool> b[N];
int s[N], fc[N];

void dfs0(int v, int f) {
  s[v] = 1;
  for (int u : e[v]) if (u != f && !fc[u]) {
    dfs0(u, v);
    s[v] += s[u];
  }
}

pair<int, int> dfs1(int v, int f, int os) {
  if (s[v] <= os) return {os, v};
  int mo = os;
  for (int u : e[v]) if (u != f && !fc[u])
    mo = max(mo, s[u]);
  pair<int, int> ans = {mo, v};
  for (int u : e[v]) if (u != f && !fc[u])
    ans = min(ans, dfs1(u, v, os + s[v] - s[u]));
  return ans;
}

void colr(int v, int cc) {
  dfs0(v, -1);
  int x = dfs1(v, -1, 0).second;
  fc[x] = cc;
  for (int y : e[x]) if (!fc[y])
    colr(y, cc + 1);
}

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    a[i].push_back((i + n - 1) % n);
    a[i].push_back((i + n + 1) % n);
  }
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    --x;
    --y;
    a[x].push_back(y);
    a[y].push_back(x);
  }

  for (int i = n - 1; i >= 0; --i) {
    sort(a[i].begin(), a[i].end());
    b[i].resize(a[i].size(), false);
  }

  map<pair<int, int>, int> bm;
  vector<int> p;
  for (int i = n - 1; i >= 0; --i) {
    for (int k = a[i].size() - 1; k >= 0; --k) if (!b[i][k]) {
      int j = a[i][k];
      b[i][k] = true;
      vector<int> p = {i};
      while (j != i) {
        int w = lower_bound(a[j].begin(), a[j].end(), p.back()) -
            a[j].begin();
        p.push_back(j);
        w = (w + 1) % a[j].size();
        b[j][w] = true;
        j = a[j][w];
      }
      if (p.size() == n) {
        if (m) continue;
        m = -1;
      }
      for (int k = 0; k < p.size(); ++k) {
        int x = p[k], y = p[(k + 1)%p.size()];
        pair<int, int> pii = {min(x,y), max(x,y)};
        if (bm.count(pii)) {
          e[top].push_back(bm[pii]);
          e[bm[pii]].push_back(top);
        } else bm[pii] = top;
      }

      ++top;
    }
  }

  colr(0, 1);
  for (int i = top - 1; i >= 0; --i)
    printf("%d ", fc[i]);
  puts("");
  return 0;
}


#include<stdio.h>
#include<bitset>
#include<vector>
#include<string.h>
#include<algorithm>
#include<memory.h>
#include<math.h>
#include<string>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<unordered_map>
#include<list>
#define E2(x,y) return !printf(x, y)
#define E1(x) return !printf(x)

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int,int,int> t3;

const int MM = 1000;

ll sq(ll x){ return x*x; }
ll rv(ll x){ ll su = 0; while(x){ su = su*10 + x%10; x /= 10; } return su; }

ll pw(ll a, ll b){
	if( !b ) return 1;
	return pw(a*a % MM, b/2) * (b%2 == 1? a : 1) % MM;
}

ll pw(ll a, ll b, ll c){
	if( !b ) return 1;
	return pw(a*a % c, b/2) * (b%2 == 1? a : 1) % c;
}

//ll rv(ll a){ return pw(a, MM-2); }

int dx[8] = {0, 1, 0, -1, -1, -1, 1, 1};
int dy[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int Ox[8] = {-1, -2, 1, 2, -1, -2, 1, 2};
int Oy[8] = {2, 1, -2, -1, -2, -1, 2, 1};
int Bx[6] = {-1, -1, 0, 1, 1, 0};
int By[6] = {-1, 0, 1, 1, 0, -1};

ll gcd(ll A, ll B){ return A? gcd(B%A, A) : B;}

pii operator*(const pii &l, const ll &r){
	return pii(l.first * r, l.second * r);
}

pii operator*(const pii &l, const pii &r){
	return pii(l.first * r.first, l.second * r.second);
}

pii operator+(const pii &l, const pii &r){
	return pii(l.first + r.first, l.second + r.second);
}

pii operator-(const pii &l, const pii &r){
	return pii(l.first - r.first, l.second - r.second);
}

pii operator%(const pii &l, const pii &r){
	return pii(l.first % r.first, l.second % r.second);
}

ll operator^(const pii &l, const pii &r){
	return (ll)l.first * r.second - (ll)l.second * r.first;
}

ll size(pii c){ return sq(c.first) + sq(c.second); }

void file(char* name){
	char buf[105];
	sprintf(buf, "%s.in", name);
	freopen(buf,"r", stdin);
	sprintf(buf, "%s.out", name);
	freopen(buf,"w", stdout);
}

int coor(vector<int> &L, int x){
	return lower_bound(L.begin(), L.end(), x) - L.begin();
}

const int MX = 200005;
const double PI = acos(-1);

auto cmp = [](const pii &l, const pii &r){return l.second !=r.second? l.second < r.second : l.first < r.first; };

char buf[MX];
int TT, N, M, K, W, a, b, c, d, e, f, g, h;

vector<pii> G[MX];
vector<int> T[MX], L[MX];
int ans[MX];
int ad = 0;

void find_region(int x, int y)
{
	L[ad].push_back(x);
	int c = lower_bound(G[y].begin(), G[y].end(), pii(x, -2)) - G[y].begin();
	if( c == 0 ) c = G[y].size() - 1;
	else c--;

	if( G[y][c].second ) return;
	G[y][c].second = ad;
	find_region(y, G[y][c].first);
}

int vst[MX], cnt[MX];

int get_cnt(int x, int p)
{
	if( vst[x] ) return cnt[x] = 0;
	cnt[x] = 1;
	for(int c : T[x]){
		if( c == p ) continue;
		cnt[x] += get_cnt(c, x);
	}
	return cnt[x];
}

void centroid(int x, int lev)
{
	if( vst[x] ) return;
	get_cnt(x, -1);

	while(T[x].size()){
		int mx = 0;
		for(int i = 0; i < T[x].size(); i++){
			if( cnt[T[x][i]] > cnt[T[x][mx]] ) mx = i;
		}
		if( cnt[T[x][mx]]*2 <= cnt[x] ) break;
		cnt[x] = cnt[x] - cnt[T[x][mx]];
		cnt[T[x][mx]] = cnt[x] + cnt[T[x][mx]];
		x = T[x][mx];
	}

	vst[x] = 1; ans[x] = lev;
	for(int c : T[x]) centroid(c, lev+1);
}

int main()
{
	scanf("%d%d", &N, &M);
	for(int i = 1; i < N; i++){
		G[i].push_back(pii(i+1, 0));
		G[i+1].push_back(pii(i, -1));
	}
	G[N].push_back(pii(1, 0));
	G[1].push_back(pii(N, -1));

	for(int i = 1; i <= M; i++){
		scanf("%d%d", &a, &b);
		G[a].push_back(pii(b, 0));
		G[b].push_back(pii(a, 0));
	}
	for(int i = 1; i <= N; i++) sort(G[i].begin(), G[i].end());
	for(int i = 1; i <= N; i++){
		for(pii &c : G[i]){
			if( c.second ) continue;
			ad++; c.second = ad;
			find_region(i, c.first);
		}
	}
	static int O[MX];
	for(int i = 1; i <= ad; i++) O[i] = i;
	for(int i = 1; i <= ad; i++) sort(L[i].begin(), L[i].end(), greater<int>());
	sort(O+1, O+ad+1, [&](const int &l, const int &r){
		return L[l] < L[r];
	});

	for(int i = 1; i <= N; i++){
		for(pii c : G[i]){
			if( i > c.first ) continue;
			int a = c.second;
			int b = lower_bound(G[c.first].begin(), G[c.first].end(), pii(i, -2)) -> second;
			if( a == -1 || b == -1 ) continue;
			T[a].push_back(b);
			T[b].push_back(a);
		}
	}

	centroid(1, 1);

	for(int i = 1; i <= ad; i++){
		printf("%d ", ans[O[i]]);
	}
}


#include<stdio.h>
#include<bitset>
#include<vector>
#include<string.h>
#include<algorithm>
#include<memory.h>
#include<math.h>
#include<string>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<unordered_map>
#include<list>
#define E2(x,y) return !printf(x, y)
#define E1(x) return !printf(x)

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int,int,int> t3;

const int MM = 1000;

ll sq(ll x){ return x*x; }
ll rv(ll x){ ll su = 0; while(x){ su = su*10 + x%10; x /= 10; } return su; }

ll pw(ll a, ll b){
	if( !b ) return 1;
	return pw(a*a % MM, b/2) * (b%2 == 1? a : 1) % MM;
}

ll pw(ll a, ll b, ll c){
	if( !b ) return 1;
	return pw(a*a % c, b/2) * (b%2 == 1? a : 1) % c;
}

//ll rv(ll a){ return pw(a, MM-2); }

int dx[8] = {0, 1, 0, -1, -1, -1, 1, 1};
int dy[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int Ox[8] = {-1, -2, 1, 2, -1, -2, 1, 2};
int Oy[8] = {2, 1, -2, -1, -2, -1, 2, 1};
int Bx[6] = {-1, -1, 0, 1, 1, 0};
int By[6] = {-1, 0, 1, 1, 0, -1};

ll gcd(ll A, ll B){ return A? gcd(B%A, A) : B;}

pii operator*(const pii &l, const ll &r){
	return pii(l.first * r, l.second * r);
}

pii operator*(const pii &l, const pii &r){
	return pii(l.first * r.first, l.second * r.second);
}

pii operator+(const pii &l, const pii &r){
	return pii(l.first + r.first, l.second + r.second);
}

pii operator-(const pii &l, const pii &r){
	return pii(l.first - r.first, l.second - r.second);
}

pii operator%(const pii &l, const pii &r){
	return pii(l.first % r.first, l.second % r.second);
}

ll operator^(const pii &l, const pii &r){
	return (ll)l.first * r.second - (ll)l.second * r.first;
}

ll size(pii c){ return sq(c.first) + sq(c.second); }

void file(char* name){
	char buf[105];
	sprintf(buf, "%s.in", name);
	freopen(buf,"r", stdin);
	sprintf(buf, "%s.out", name);
	freopen(buf,"w", stdout);
}

int coor(vector<int> &L, int x){
	return lower_bound(L.begin(), L.end(), x) - L.begin();
}

const int MX = 200005;
const double PI = acos(-1);

auto cmp = [](const pii &l, const pii &r){return l.second !=r.second? l.second < r.second : l.first < r.first; };

char buf[MX];
int TT, N, M, K, W, a, b, c, d, e, f, g, h;

vector<pii> G[MX];
vector<int> T[MX], L[MX];
int ans[MX];
int ad = 0;

void find_region(int x, int y)
{
	L[ad].push_back(x);
	int c = lower_bound(G[y].begin(), G[y].end(), pii(x, -2)) - G[y].begin();
	if( c == 0 ) c = G[y].size() - 1;
	else c--;

	if( G[y][c].second ) return;
	G[y][c].second = ad;
	find_region(y, G[y][c].first);
}

int vst[MX], cnt[MX];

int get_cnt(int x, int p)
{
	if( vst[x] ) return cnt[x] = 0;
	cnt[x] = 1;
	for(int c : T[x]){
		if( c == p ) continue;
		cnt[x] += get_cnt(c, x);
	}
	return cnt[x];
}

void centroid(int x, int lev)
{
	if( vst[x] ) return;
	get_cnt(x, -1);

	while(1){
		int mx = 0;
		for(int i = 0; i < T[x].size(); i++){
			if( cnt[T[x][i]] > cnt[T[x][mx]] ) mx = i;
		}
		if( cnt[T[x][mx]]*2 <= cnt[x] ) break;
		cnt[T[x][mx]] = cnt[x];
		cnt[x] = cnt[T[x][mx]] - cnt[x];
		x = T[x][mx];
	}

	vst[x] = 1; ans[x] = lev;
	for(int c : T[x]) centroid(c, lev+1);
}

int main()
{
	scanf("%d%d", &N, &M);
	for(int i = 1; i < N; i++){
		G[i].push_back(pii(i+1, 0));
		G[i+1].push_back(pii(i, -1));
	}
	G[N].push_back(pii(1, 0));
	G[1].push_back(pii(N, -1));

	for(int i = 1; i <= M; i++){
		scanf("%d%d", &a, &b);
		G[a].push_back(pii(b, 0));
		G[b].push_back(pii(a, 0));
	}
	for(int i = 1; i <= N; i++) sort(G[i].begin(), G[i].end());
	for(int i = 1; i <= N; i++){
		for(pii &c : G[i]){
			if( c.second ) continue;
			ad++; c.second = ad;
			find_region(i, c.first);
		}
	}
	static int O[MX];
	for(int i = 1; i <= ad; i++) O[i] = i;
	for(int i = 1; i <= ad; i++) sort(L[i].begin(), L[i].end(), greater<int>());
	sort(O+1, O+ad+1, [&](const int &l, const int &r){
		return L[l] < L[r];
	});

	for(int i = 1; i <= N; i++){
		for(pii c : G[i]){
			if( i > c.first ) continue;
			int a = c.second;
			int b = lower_bound(G[c.first].begin(), G[c.first].end(), pii(i, -2)) -> second;
			if( a == -1 || b == -1 ) continue;
			T[a].push_back(b);
			T[b].push_back(a);
		}
	}

	centroid(1, 1);

	for(int i = 1; i <= ad; i++){
		printf("%d ", ans[O[i]]);
	}
}


#include<stdio.h>
#include<bitset>
#include<vector>
#include<string.h>
#include<algorithm>
#include<memory.h>
#include<math.h>
#include<string>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<unordered_map>
#include<list>
#define E2(x,y) return !printf(x, y)
#define E1(x) return !printf(x)

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int,int,int> t3;

const int MM = 1000;

ll sq(ll x){ return x*x; }
ll rv(ll x){ ll su = 0; while(x){ su = su*10 + x%10; x /= 10; } return su; }

ll pw(ll a, ll b){
	if( !b ) return 1;
	return pw(a*a % MM, b/2) * (b%2 == 1? a : 1) % MM;
}

ll pw(ll a, ll b, ll c){
	if( !b ) return 1;
	return pw(a*a % c, b/2) * (b%2 == 1? a : 1) % c;
}

//ll rv(ll a){ return pw(a, MM-2); }

int dx[8] = {0, 1, 0, -1, -1, -1, 1, 1};
int dy[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int Ox[8] = {-1, -2, 1, 2, -1, -2, 1, 2};
int Oy[8] = {2, 1, -2, -1, -2, -1, 2, 1};
int Bx[6] = {-1, -1, 0, 1, 1, 0};
int By[6] = {-1, 0, 1, 1, 0, -1};

ll gcd(ll A, ll B){ return A? gcd(B%A, A) : B;}

pii operator*(const pii &l, const ll &r){
	return pii(l.first * r, l.second * r);
}

pii operator*(const pii &l, const pii &r){
	return pii(l.first * r.first, l.second * r.second);
}

pii operator+(const pii &l, const pii &r){
	return pii(l.first + r.first, l.second + r.second);
}

pii operator-(const pii &l, const pii &r){
	return pii(l.first - r.first, l.second - r.second);
}

pii operator%(const pii &l, const pii &r){
	return pii(l.first % r.first, l.second % r.second);
}

ll operator^(const pii &l, const pii &r){
	return (ll)l.first * r.second - (ll)l.second * r.first;
}

ll size(pii c){ return sq(c.first) + sq(c.second); }

void file(char* name){
	char buf[105];
	sprintf(buf, "%s.in", name);
	freopen(buf,"r", stdin);
	sprintf(buf, "%s.out", name);
	freopen(buf,"w", stdout);
}

int coor(vector<int> &L, int x){
	return lower_bound(L.begin(), L.end(), x) - L.begin();
}

const int MX = 200005;
const double PI = acos(-1);

auto cmp = [](const pii &l, const pii &r){return l.second !=r.second? l.second < r.second : l.first < r.first; };

char buf[MX];
int TT, N, M, K, W, a, b, c, d, e, f, g, h;

vector<pii> G[MX];
vector<int> T[MX], L[MX];
int ans[MX];
int ad = 0;

void find_region(int x, int y)
{
	L[ad].push_back(x);
	int c = lower_bound(G[y].begin(), G[y].end(), pii(x, -2)) - G[y].begin();
	if( c == 0 ) c = G[y].size() - 1;
	else c--;

	if( G[y][c].second ) return;
	G[y][c].second = ad;
	find_region(y, G[y][c].first);
}

int vst[MX], cnt[MX];

int get_cnt(int x, int p)
{
	if( vst[x] ) return cnt[x] = 0;
	cnt[x] = 1;
	for(int c : T[x]){
		if( c == p ) continue;
		cnt[x] += get_cnt(c, x);
	}
	return cnt[x];
}

void centroid(int x, int lev)
{
	if( vst[x] ) return;
	get_cnt(x, -1);

	while(1){
		int mx = 0;
		for(int i = 0; i < T[x].size(); i++){
			if( cnt[T[x][i]] < cnt[T[x][mx]] ) mx = i;
		}
		if( cnt[T[x][mx]]*2 <= cnt[x] ) break;
		cnt[T[x][mx]] += cnt[x];
		cnt[x] = cnt[T[x][mx]] - cnt[x];
		x = T[x][mx];
	}

	vst[x] = 1; ans[x] = lev;
	for(int c : T[x]) centroid(c, lev+1);
}

int main()
{
	scanf("%d%d", &N, &M);
	for(int i = 1; i < N; i++){
		G[i].push_back(pii(i+1, 0));
		G[i+1].push_back(pii(i, -1));
	}
	G[N].push_back(pii(1, 0));
	G[1].push_back(pii(N, -1));

	for(int i = 1; i <= M; i++){
		scanf("%d%d", &a, &b);
		G[a].push_back(pii(b, 0));
		G[b].push_back(pii(a, 0));
	}
	for(int i = 1; i <= N; i++) sort(G[i].begin(), G[i].end());
	for(int i = 1; i <= N; i++){
		for(pii &c : G[i]){
			if( c.second ) continue;
			ad++; c.second = ad;
			find_region(i, c.first);
		}
	}
	static int O[MX];
	for(int i = 1; i <= ad; i++) O[i] = i;
	for(int i = 1; i <= ad; i++) sort(L[i].begin(), L[i].end(), greater<int>());
	sort(O+1, O+N+1, [&](const int &l, const int &r){
		return L[l] < L[r];
	});

	for(int i = 1; i <= N; i++){
		for(pii c : G[i]){
			if( i > c.first ) continue;
			int a = c.second;
			int b = lower_bound(G[c.first].begin(), G[c.first].end(), pii(i, -2)) -> second;
			if( a == -1 || b == -1 ) continue;
			T[a].push_back(b);
			T[b].push_back(a);
		}
	}

	centroid(1, 1);

	for(int i = 1; i <= ad; i++){
		printf("%d ", ans[i]);
	}
}


#include<stdio.h>
#include<bitset>
#include<vector>
#include<string.h>
#include<algorithm>
#include<memory.h>
#include<math.h>
#include<string>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<unordered_map>
#include<list>
#define E2(x,y) return !printf(x, y)
#define E1(x) return !printf(x)

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int,int,int> t3;

const int MM = 1000;

ll sq(ll x){ return x*x; }
ll rv(ll x){ ll su = 0; while(x){ su = su*10 + x%10; x /= 10; } return su; }

ll pw(ll a, ll b){
	if( !b ) return 1;
	return pw(a*a % MM, b/2) * (b%2 == 1? a : 1) % MM;
}

ll pw(ll a, ll b, ll c){
	if( !b ) return 1;
	return pw(a*a % c, b/2) * (b%2 == 1? a : 1) % c;
}

//ll rv(ll a){ return pw(a, MM-2); }

int dx[8] = {0, 1, 0, -1, -1, -1, 1, 1};
int dy[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int Ox[8] = {-1, -2, 1, 2, -1, -2, 1, 2};
int Oy[8] = {2, 1, -2, -1, -2, -1, 2, 1};
int Bx[6] = {-1, -1, 0, 1, 1, 0};
int By[6] = {-1, 0, 1, 1, 0, -1};

ll gcd(ll A, ll B){ return A? gcd(B%A, A) : B;}

pii operator*(const pii &l, const ll &r){
	return pii(l.first * r, l.second * r);
}

pii operator*(const pii &l, const pii &r){
	return pii(l.first * r.first, l.second * r.second);
}

pii operator+(const pii &l, const pii &r){
	return pii(l.first + r.first, l.second + r.second);
}

pii operator-(const pii &l, const pii &r){
	return pii(l.first - r.first, l.second - r.second);
}

pii operator%(const pii &l, const pii &r){
	return pii(l.first % r.first, l.second % r.second);
}

ll operator^(const pii &l, const pii &r){
	return (ll)l.first * r.second - (ll)l.second * r.first;
}

ll size(pii c){ return sq(c.first) + sq(c.second); }

void file(char* name){
	char buf[105];
	sprintf(buf, "%s.in", name);
	freopen(buf,"r", stdin);
	sprintf(buf, "%s.out", name);
	freopen(buf,"w", stdout);
}

int coor(vector<int> &L, int x){
	return lower_bound(L.begin(), L.end(), x) - L.begin();
}

const int MX = 200005;
const double PI = acos(-1);

auto cmp = [](const pii &l, const pii &r){return l.second !=r.second? l.second < r.second : l.first < r.first; };

char buf[MX];
int TT, N, M, K, W, a, b, c, d, e, f, g, h;

vector<pii> G[MX];
vector<int> T[MX], L[MX];
int ans[MX];
int ad = 0;

void find_region(int x, int y)
{
	L[ad].push_back(x);
	int c = lower_bound(G[y].begin(), G[y].end(), pii(x, -2)) - G[y].begin();
	if( c == 0 ) c = G[y].size() - 1;
	else c--;

	if( G[y][c].second ) return;
	G[y][c].second = ad;
	find_region(y, G[y][c].first);
}

int vst[MX], cnt[MX];

int get_cnt(int x, int p)
{
	if( vst[x] ) return cnt[x] = 0;
	cnt[x] = 1;
	for(int c : T[x]){
		if( c == p ) continue;
		cnt[x] += get_cnt(c, x);
	}
	return cnt[x];
}

void centroid(int x, int lev)
{
	if( vst[x] ) return;
	get_cnt(x, -1);

	while(1){
		int mx = 0;
		for(int i = 0; i < T[x].size(); i++){
			if( cnt[T[x][i]] < cnt[T[x][mx]] ) mx = i;
		}
		if( cnt[T[x][mx]]*2 <= cnt[x] ) break;
		cnt[T[x][mx]] += cnt[x];
		cnt[x] = cnt[T[x][mx]] - cnt[x];
		x = T[x][mx];
	}

	vst[x] = 1; ans[x] = lev;
	for(int c : T[x]) centroid(c, lev+1);
}

int main()
{
	scanf("%d%d", &N, &M);
	for(int i = 1; i < N; i++){
		G[i].push_back(pii(i+1, 0));
		G[i+1].push_back(pii(i, -1));
	}
	G[N].push_back(pii(1, 0));
	G[1].push_back(pii(N, -1));

	for(int i = 1; i <= M; i++){
		scanf("%d%d", &a, &b);
		G[a].push_back(pii(b, 0));
		G[b].push_back(pii(a, 0));
	}
	for(int i = 1; i <= N; i++) sort(G[i].begin(), G[i].end());
	for(int i = 1; i <= N; i++){
		for(pii &c : G[i]){
			if( c.second ) continue;
			ad++; c.second = ad;
			find_region(i, c.first);
		}
	}
	static int O[MX];
	for(int i = 1; i <= ad; i++) O[i] = i;
	for(int i = 1; i <= ad; i++) sort(L[i].begin(), L[i].end(), greater<int>());
	sort(O+1, O+ad+1, [&](const int &l, const int &r){
		return L[l] < L[r];
	});

	for(int i = 1; i <= N; i++){
		for(pii c : G[i]){
			if( i > c.first ) continue;
			int a = c.second;
			int b = lower_bound(G[c.first].begin(), G[c.first].end(), pii(i, -2)) -> second;
			if( a == -1 || b == -1 ) continue;
			T[a].push_back(b);
			T[b].push_back(a);
		}
	}

	centroid(1, 1);

	for(int i = 1; i <= ad; i++){
		printf("%d ", ans[O[i]]);
	}
}


#include <bits/stdc++.h>
using namespace std;

inline void check_max(int& a, int b) {
  if (a < b) a = b;
}

const int MAX_N = 100100;

int n, m;
vector<int> ed[MAX_N];
int color[MAX_N];
bool valid[MAX_N];

int centroid(int rt) {
  static int que[MAX_N];
  static int par[MAX_N];
  int f = 0, b = 0;
  que[b++] = rt;
  par[rt] = 0;
  while (f < b) {
    int u = que[f++];
    for (int v : ed[u]) {
      if (!valid[v] || v == par[u]) continue;
      que[b++] = v;
      par[v] = u;
    }
  }
  static int sz[MAX_N];
  static int ms[MAX_N];
  rt = -1;
  for (int i = b - 1; i >= 0; --i) {
    int u = que[i];
    sz[u] = 1;
    ms[u] = 0;
    for (int v : ed[u]) {
      if (!valid[v] || v == par[u]) continue;
      sz[u] += sz[v];
      check_max(ms[u], sz[v]);
    }
    check_max(ms[u], b - sz[u]);
    if (rt == -1 || ms[u] < ms[rt]) rt = u;
  }
  return rt;
}

void dfs(int u, int c) {
  u = centroid(u);
  valid[u] = false;
  color[u] = c;
  for (int v : ed[u]) {
    if (!valid[v]) continue;
    dfs(v, c + 1);
  }
}

vector<pair<int, int>> es;
map<int, int> go[MAX_N];

void build(int l, int r, int u) {
  for (int ll = l; ll < r; ++ll) {
    if (go[ll].empty()) continue;
    auto it = prev(go[ll].end());
    int rr = it->first, v = it->second;
    go[ll].erase(it);
    ed[u].push_back(v);
    ed[v].push_back(u);
    build(ll, rr, v);
    ll = rr - 1;
  }
}

int main() {
  scanf("%d%d", &n, &m);
  int a, b;
  es.emplace_back(1, n);
  for (int i = 0; i < m; ++i) {
    scanf("%d%d", &a, &b);
    if (a > b) swap(a, b);
    es.emplace_back(a, b);
  }
  sort(es.begin(), es.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
    return a.second == b.second ? a.first < b.first : a.second < b.second;
  });
  int idx = 0, rt;
  for (const auto& pr : es) {
    go[pr.first][pr.second] = ++idx;
    if (pr == make_pair(1, n)) rt = idx;
  }
  go[1].erase(n);
  build(1, n, rt);
  fill(valid, valid + m + 2, true);
  dfs(1, 1);
  for (int i = 1; i <= m + 1; ++i) {
    printf("%d%c", color[i], " \n"[i == m + 1]);
  }
  return 0;
}


#ifdef __GNUC__
#pragma GCC target("sse4,avx")
#endif
#include <immintrin.h>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <cstdint>
#include <numeric>

struct Solution {
  int n;
  std::vector<std::vector<int>> diagonals;
  std::vector<std::vector<int>> graph;
  std::vector<int> colors;
  std::vector<int> subtreeSizes;
  void build_graph() {
    std::vector<std::pair<int, int>> next(n);
    for (int i = 1; i < n; i++) {
      next[i].first = i - 1;
      next[i].second = -1;
    }
    graph.clear();
    diagonals[n - 1].insert(diagonals[n - 1].begin(), 0);
    for (int i = 2; i < n; i++) {
      if (diagonals[i].empty()) {
        continue;
      }
      if (diagonals[i][0] > i) {
        continue;
      }
      int firstNode = graph.size();
      for (int k = 0; k < diagonals[i].size(); k++) {
        int v = diagonals[i][k];
        if (v > i) break;
        int nv;
        if (k + 1 < diagonals[i].size()) {
          nv = diagonals[i][k + 1];
        } else {
          nv = i;
        }
        int node = graph.size();
        graph.emplace_back();
        for (int j = nv; j != v; j = next[j].first) {
          int other = next[j].second;
          if (other >= 0) {
            graph[node].push_back(other);
            graph[other].push_back(node);
          }
        }
        if (k > 0) {
          graph[node].push_back(node - 1);
          graph[node - 1].push_back(node);
        }
      }
      next[i].first = diagonals[i][0];
      next[i].second = firstNode;
    }
  }

  void dfs(int v, int prev) {
    int size = 1;
    for (int nv : graph[v]) {
      if (nv != prev && colors[nv] == -1) {
        dfs(nv, v);
        size += subtreeSizes[nv];
      }
    }
    subtreeSizes[v] = size;
  }

  void color_part(int v, int color) {
    dfs(v , -1);
    int prev = -1;
    int all = subtreeSizes[v];
    while (true) {
      int maxSize = 0;
      int maxNv = -1;
      for (int nv : graph[v]) {
        if (nv != prev && colors[nv] == -1) {
          if (subtreeSizes[nv] > maxSize) {
            maxSize = subtreeSizes[nv];
            maxNv = nv;
          }
        }
      }
      if (maxSize <= all / 2) {
        break;
      }
      prev = v;
      v = maxNv;
    }
    colors[v] = color;
    for (int nv : graph[v]) {
      if (colors[nv] == -1) {
        color_part(nv, color + 1);
      }
    }
  }

  void color_graph() {
    colors.assign(graph.size(), -1);
    subtreeSizes.resize(graph.size());
    color_part(0, 1);
  }

  void run(std::istream& in, std::ostream& out) {
    in >> n;
    diagonals.assign(n, std::vector<int>());
    int m;
    in >> m;
    for (int i = 0; i < m; i++) {
      int a, b;
      in >> a >> b;
      a--;
      b--;
      diagonals[a].push_back(b);
      diagonals[b].push_back(a);
    }
    for (std::vector<int>& d : diagonals) {
      std::sort(d.begin(), d.end());
    }
    build_graph();
    color_graph();
    for (int c : colors) {
      out << c << " ";
    }
    out << std::endl;
  }
};

int main() {
  std::cin.sync_with_stdio(false);
  std::cin.tie(nullptr);
  Solution().run(std::cin, std::cout);
  return 0;
}


#include <bits/stdc++.h>

#define itn int
#define LL long long
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define all(x) (x).begin(), (x).end()

#define sz(x) (int)((x).size())

#ifdef OLBOEB
	#define return std::cerr << __FUNCTION__ << "\n"; return
#endif  // OLBOEB

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

inline pair<int, int> mp(int x, int y) {
	return {min(x, y), max(x, y)};
}

void mark_sizes(const vector<vector<int>>& ed, const vector<int>& edges, const vector<char>& forb, vector<int>& size, int v, int pr = -1) {
	size[v] = 1;
	for (int ed_num : ed[v]) {
		if (forb[ed_num]) {
			continue;
		}
		int x = edges[ed_num] - v;
		if (x == pr) {
			continue;
		}
		mark_sizes(ed, edges, forb, size, x, v);
		size[v] += size[x];
	}
}

int find_centroid(const vector<vector<int>>& ed, const vector<int>& edges, const vector<char>& forb, const vector<int>& size, int total, int v, int pr = -1) {
	int thres = (total + 1) / 2;
	for (int ed_num : ed[v]) {
		if (forb[ed_num]) {
			continue;
		}
		int x = edges[ed_num] - v;
		if (x == pr) {
			continue;
		}
		if (size[x] >= thres) {
			return find_centroid(ed, edges, forb, size, total, x, v);
		}
	}
	return v;
}

vector<int> get_neigs(const vector<vector<int>>& ed, const vector<int>& edges, vector<char>& forb, int v) {
	vector<int> res;
	for (int ed_num : ed[v]) {
		if (forb[ed_num]) {
			continue;
		}
		int x = edges[ed_num] - v;
		forb[ed_num] = 1;
		res.push_back(x);
	}
	return res;
}

int main(){
	int n = nxt(), m = nxt();
	vector<vector<int>> a(n);
	for (int i = 0; i < n; ++i) {
		a[i].push_back((i + 1) % n);
		a[i].push_back((i + n - 1) % n);
	}

	for (int i = 0; i < m; ++i) {
		int u = nxt() - 1, v = nxt() - 1;
		a[u].push_back(v);
		a[v].push_back(u);
	}

	vector<int> ends(n);
	for (int i = 0; i < n; ++i) {
		for (int &x : a[i]) {
			if (x < i) {
				x += n;
			}
		}
		sort(all(a[i]));
		ends[i] = lower_bound(all(a[i]), n) - a[i].begin();
		for (int &x : a[i]) {
			if (x >= n) {
				x -= n;
			}
		}
	}

	vector<vector<int>> rgns;
	set<pair<int, int>> S;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < (int)a[i].size() - 1; ++j) {
			if (S.find({i, a[i][j]}) != S.end()) {
				continue;
			}
			rgns.push_back({});
			int cur = i;
			int index = j;
			do {
				rgns.back().push_back(cur);
				int old = cur;
				cur = a[cur][index];
				S.insert({old, cur});
				if (old > cur) {
					index = lower_bound(a[cur].begin(), a[cur].begin() + ends[cur], old) - a[cur].begin();
				} else {
					index = lower_bound(a[cur].begin() + ends[cur], a[cur].end(), old) - a[cur].begin();
				}
				--index;
				assert(index >= 0);
			} while (cur != i);
		}
	}

	int cnt = rgns.size();
	vector<vector<int>> ed(cnt);
	map<pair<int, int>, int> lst;
	vector<int> edges;
	for (int i = 0; i < cnt; ++i) {
		int ls = rgns[i].back();
		for (int x : rgns[i]) {
			auto p = mp(x, ls);
			if (abs(ls - x) > 1 && abs(ls - x) < n - 1) {
				if (lst.count(p)) {
					int j = lst[p];
					ed[i].push_back(edges.size());
					ed[j].push_back(edges.size());
					edges.push_back(i + j);
				} else {
					lst[p] = i;
				}
			}
			ls = x;
		}
	}

	int edges_cnt = edges.size();
	vector<char> forb(edges_cnt);
	vector<int> color(cnt);
	vector<int> size(cnt);
	vector<char> used(cnt);
	vector<int> roots = {0};
	int curcolor = 1;
	while (!roots.empty()) {
		vector<int> new_roots;
		for (int root : roots) {
			mark_sizes(ed, edges, forb, size, root);
			int centroid = find_centroid(ed, edges, forb, size, size[root], root);
			color[centroid] = curcolor;
			auto neigs = get_neigs(ed, edges, forb, centroid);
			new_roots.insert(new_roots.end(), all(neigs));
		}
		roots.swap(new_roots);
		++curcolor;
	}

	vector<pair<vector<int>, int>> regions(cnt);
	for (int i = 0; i < cnt; ++i) {
		regions[i] = {rgns[i], i};
		sort(all(regions[i].first));
		reverse(all(regions[i].first));
	}

	sort(all(regions));
	for (int i = 0; i < cnt; ++i) {
		printf("%d ", color[regions[i].second]);
	}
	printf("\n");

	return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

struct Region{
    vector<int> vertices;
    iii id;
};

const int N = 100002;
int n, diags, next_[N], subsize[N], ans[N];
ii arr[N];
bool removed[N];
set<ii> diagonals;
Region regions[N];
map<ii, int> separates;
set<int> adj[N];

bool is_diagonal(int a, int b){
    return (diagonals.find({min(a, b), max(a, b)}) != diagonals.end());
}

bool comp_diags(ii a, ii b){
    int x1 = min(a.ss-a.ff-1, n-(a.ss-a.ff+1));
    int x2 = min(b.ss-b.ff-1, n-(b.ss-b.ff+1));
    return x1 < x2;
}

bool comp_regions(Region a, Region b){
    return a.id < b.id;
}

void dfs0(int v, int par){
    subsize[v] = 1;
    for(auto it : adj[v])
        if(it != par){
            dfs0(it, v);
            subsize[v] += subsize[it];
        }
}

int dfs1(int v, int par, int tot){
    for(auto vv : adj[v])
        if(vv != par && subsize[vv] > (tot/2))
            return dfs1(vv, v, tot);
    return v;
}

void decompose(int v, int col){

    dfs0(v, -1);
    int centroid = dfs1(v, -1, subsize[v]);
    ans[centroid] = col;
// cout<<"found centroid "<<centroid<<" at v = "<<v<<endl;

    for(auto it : adj[centroid]){
        adj[it].erase(centroid);
        decompose(it, col+1);
    }
    adj[centroid].clear();
}

int main(){

    // ios_base::sync_with_stdio(0);
    // cin.tie(0);

    scanf("%d%d", &n, &diags);
    for(int i=1;i<=diags;i++){
        scanf("%d%d", &arr[i].ff, &arr[i].ss);
        if(arr[i].ff > arr[i].ss)
            swap(arr[i].ff, arr[i].ss);
        diagonals.insert(arr[i]);
    }
    sort(arr+1, arr+diags+1, comp_diags);

    if(diags == 0){
        printf("1\n");
        return 0;
    }

    for(int i=1;i<=n;i++){
        next_[i] = i+1;
        next_[n] = 1;
    }

    for(int i=1;i<=diags;i++){
        int lval = arr[i].ss - arr[i].ff - 1;
        int rval = n - (arr[i].ss - arr[i].ff + 1);
        vector<int> vertices;
        if(lval <= rval){
            int curr = arr[i].ff;
            while(1){
                if(curr != arr[i].ff && curr != arr[i].ss)
                    removed[curr] = true;
                vertices.pb(curr);
                if(curr == arr[i].ss)   break;
                curr = next_[curr];
            }
            next_[arr[i].ff] = arr[i].ss;
        }
        else{
            int curr = arr[i].ss;
            while(1){
                if(curr != arr[i].ff && curr != arr[i].ss)
                    removed[curr] = true;
                vertices.pb(curr);
                if(curr == arr[i].ff)   break;
                curr = next_[curr];
            }
            next_[arr[i].ss] = arr[i].ff;
        }

        regions[i].vertices = vertices;
        sort(vertices.begin(), vertices.end());
        regions[i].id = iii (vertices[(int)vertices.size()-1], ii (vertices[(int)vertices.size()-2], vertices[(int)vertices.size()-3]));
    }

    int k = diags+1;
    vector<int> vertices;
    for(int i=1;i<=n;i++)
        if(!removed[i])
            vertices.pb(i);
    regions[k].vertices = vertices;
    sort(vertices.begin(), vertices.end());
    regions[k].id = iii (vertices[(int)vertices.size()-1], ii (vertices[(int)vertices.size()-2], vertices[(int)vertices.size()-3]));

    sort(regions+1, regions+k+1, comp_regions);

// cout<<"regions:\n";
// for(int i=1;i<=k;i++){
//     cout<<i<<": ";for(auto it : regions[i].vertices)    cout<<it<<" ";cout<<"and id = "<<regions[i].id.ff<<":"<<regions[i].id.ss.ff<<":"<<regions[i].id.ss.ss<<endl;
// }cout<<endl;

    for(int i=1;i<=k;i++){
        regions[i].vertices.pb(regions[i].vertices[0]);
        for(int j=1;j<(int)regions[i].vertices.size();j++){
            if(is_diagonal(regions[i].vertices[j], regions[i].vertices[j-1])){
                if(separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}] == 0){
                    separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}] = i;
                }
                else{
                    int x = separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}];
                    adj[x].insert(i);
                    adj[i].insert(x);
                }
            }
        }
    }

// cout<<"adj:\n";
// for(int i=1;i<=k;i++){
//     cout<<i<<": ";for(auto j : adj[i])  cout<<j<<" ";cout<<endl;
// }cout<<endl;

    decompose(1, 1);
    for(int i=1;i<=k;i++)
        printf("%d ", ans[i]);
    return 0;
}


//satyaki3794
#include <bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

ll gcd(ll a, ll b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

struct Region{
    vector<int> vertices;
    iii id;
};

const int N = 100002;
int n, diags, next_[N], subsize[N], ans[N];
ii arr[N];
bool removed[N];
set<ii> diagonals;
Region regions[N];
map<ii, int> separates;
vector<int> adj[N];

bool is_diagonal(int a, int b){
    return (diagonals.find({min(a, b), max(a, b)}) != diagonals.end());
}

bool comp_diags(ii a, ii b){
    int x1 = min(a.ss-a.ff-1, n-(a.ss-a.ff+1));
    int x2 = min(b.ss-b.ff-1, n-(b.ss-b.ff+1));
    return x1 < x2;
}

bool comp_regions(Region a, Region b){
    return a.id < b.id;
}

void dfs0(int v, int par){
    subsize[v] = 1;
    for(auto it : adj[v])
        if(it != par){
            dfs0(it, v);
            subsize[v] += subsize[it];
        }
}

int dfs1(int v, int par, int tot){
    for(auto vv : adj[v])
        if(vv != par && subsize[vv] > (tot/2))
            return dfs1(vv, v, tot);
    return v;
}

void dfs2(int v, int par, int col){
    ans[v] = col;
    for(auto vv : adj[v])
        if(vv != par)
            dfs2(vv, v, col+1);
}

int main(){

    // ios_base::sync_with_stdio(0);
    // cin.tie(0);

    scanf("%d%d", &n, &diags);
    for(int i=1;i<=diags;i++){
        scanf("%d%d", &arr[i].ff, &arr[i].ss);
        if(arr[i].ff > arr[i].ss)
            swap(arr[i].ff, arr[i].ss);
        diagonals.insert(arr[i]);
    }
    sort(arr+1, arr+diags+1, comp_diags);

    if(diags == 0){
        printf("1\n");
        return 0;
    }

    for(int i=1;i<=n;i++){
        next_[i] = i+1;
        next_[n] = 1;
    }

    for(int i=1;i<=diags;i++){
        int lval = arr[i].ss - arr[i].ff - 1;
        int rval = n - (arr[i].ss - arr[i].ff + 1);
        vector<int> vertices;
        if(lval <= rval){
            int curr = arr[i].ff;
            while(1){
                if(curr != arr[i].ff && curr != arr[i].ss)
                    removed[curr] = true;
                vertices.pb(curr);
                if(curr == arr[i].ss)   break;
                curr = next_[curr];
            }
            next_[arr[i].ff] = arr[i].ss;
        }
        else{
            int curr = arr[i].ss;
            while(1){
                if(curr != arr[i].ff && curr != arr[i].ss)
                    removed[curr] = true;
                vertices.pb(curr);
                if(curr == arr[i].ff)   break;
                curr = next_[curr];
            }
            next_[arr[i].ss] = arr[i].ff;
        }

        regions[i].vertices = vertices;
        sort(vertices.begin(), vertices.end());
        regions[i].id = iii (vertices[(int)vertices.size()-1], ii (vertices[(int)vertices.size()-2], vertices[(int)vertices.size()-3]));
    }

    int k = diags+1;
    vector<int> vertices;
    for(int i=1;i<=n;i++)
        if(!removed[i])
            vertices.pb(i);
    regions[k].vertices = vertices;
    sort(vertices.begin(), vertices.end());
    regions[k].id = iii (vertices[(int)vertices.size()-1], ii (vertices[(int)vertices.size()-2], vertices[(int)vertices.size()-3]));

    sort(regions+1, regions+k+1, comp_regions);

// cout<<"regions:\n";
// for(int i=1;i<=k;i++){
//     cout<<i<<": ";for(auto it : regions[i].vertices)    cout<<it<<" ";cout<<"and id = "<<regions[i].id.ff<<":"<<regions[i].id.ss.ff<<":"<<regions[i].id.ss.ss<<endl;
// }cout<<endl;

    for(int i=1;i<=k;i++){
        regions[i].vertices.pb(regions[i].vertices[0]);
        for(int j=1;j<(int)regions[i].vertices.size();j++){
            if(is_diagonal(regions[i].vertices[j], regions[i].vertices[j-1])){
                if(separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}] == 0){
                    separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}] = i;
                }
                else{
                    int x = separates[{min(regions[i].vertices[j], regions[i].vertices[j-1]), max(regions[i].vertices[j], regions[i].vertices[j-1])}];
                    adj[x].pb(i);
                    adj[i].pb(x);
                }
            }
        }
    }

// cout<<"adj:\n";
// for(int i=1;i<=n;i++){
//     cout<<i<<": ";for(auto j : adj[i])  cout<<j<<" ";cout<<endl;
// }cout<<endl;

    dfs0(1, -1);
    int centroid = dfs1(1, -1, subsize[1]);
    dfs2(centroid, -1, 1);

    for(int i=1;i<=k;i++)
        printf("%d ", ans[i]);
    return 0;
}


#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define ll long long
#define ull unsigned long long
#define all(aaa) aaa.begin(), aaa.end()
#pragma warning(disable : 4996)

const int N = 1e5 + 5;
int col[N], sz[N];
set<pair<int, int>> d[N];
vector<int> d2[N], g[N];
map<vector<int>, int> mp;
int n, m;

int f(int a, int b = n) {
	if (a < 0)
		a += b;
	if (a >= b)
		a -= b;
	return a;
}

void dfs(int node, int anc = -1) {
	sz[node] = 1;
	for (int to : g[node]) {
		if (to != anc && !col[to]) {
			dfs(to, node);
			sz[node] += sz[to];
		}
	}
}

int findCentroid(int node, int half, int anc = -1) {
	for (int to : g[node]) {
		if (!col[to] && to != anc && sz[to] > half)
			return findCentroid(to, half, node);
	}
	return node;
}

void solve(int node, int h = 1) {
	dfs(node);
	node = findCentroid(node, sz[node] / 2);
	col[node] = h;
	for (int to : g[node]) {
		if (!col[to])
			solve(to, h + 1);
	}
}

signed main() {
#ifdef HOME
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;

	if (m == 0) {
		cout << 1;
		return 0;
	}

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		d2[a].push_back(b);
		d2[b].push_back(a);
		d[a].insert({ f(b - a), b });
		d[b].insert({ f(a - b), a });
	}

	for (int i = 0; i < n; i++) {
		d[i].insert({ 1, f(i + 1) });
		d[i].insert({ n - 1, f(i - 1) });
		d2[i].push_back(f(i - 1));
		d2[i].push_back(f(i + 1));
	}

	vector<vector<int>> faces;

	for (int i = 0; i < n; i++) {
		while (!d[i].empty()) {
			int x = i, y = d[i].begin()->second;
			vector<int> fc;
			set<pair<int, int>> used = { *d[i].begin() };
			while (true) {
				fc.push_back(y);
				auto it = d[y].upper_bound({ f(x - y), x });
				if (it == d[y].end())
					it = d[y].begin();
				if (used.count(*it))
					break;
				x = y;
				y = it->second;
				used.insert(*it);
			}
			for (int j = 0; j < fc.size(); j++) {
				int k = j == fc.size() - 1 ? 0 : j + 1;
				d[fc[j]].erase({ f(fc[k] - fc[j]), fc[k] });
			}
			if (fc.size() == n)
				continue;
			sort(fc.rbegin(), fc.rend());
			faces.push_back(fc);
		}
	}

	sort(faces.begin(), faces.end());

	for (int i = 0; i < faces.size(); i++) {
		for (int j = 0; j < faces[i].size(); j++) {
			vector<int> v;
			for (int k = 0; k < 3; k++) {
				v.push_back({ faces[i][f(j + k, faces[i].size())] });
			}
			mp[v] = i;
		}
	}

	for (int i = 0; i < n; i++) {
		sort(all(d2[i]), [&](int x, int y) {
			return f(x - i) < f(y - i);
		});
		for (int j = 1; j < (int)d2[i].size() - 1; j++) {
			int x = mp[{d2[i][j - 1], i, d2[i][j]}],
				y = mp[{d2[i][j], i, d2[i][j + 1]}];
			g[x].push_back(y);
		}
	}

	solve(0);

	for (int i = 0; i < faces.size(); i++)
		cout << col[i] << " ";

	return 0;
}


#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define ll long long
#define ull unsigned long long
#define all(aaa) aaa.begin(), aaa.end()
#pragma warning(disable : 4996)

int n, m;

struct cmp {
	int s;
	cmp(int s) : s(s) {}
	bool operator ()(int a, int b) const {
		a = a - s + n;
		b = b - s + n;
		if (a >= n)
			a -= n;
		if (b >= n)
			b -= n;
	}
};

const int N = 1e5 + 5;
int col[N], sz[N];
set<pair<int, int>> d[N];
vector<int> d2[N], g[N];
map<vector<int>, int> mp;

int f(int a, int b = n) {
	if (a < 0)
		a += b;
	if (a >= b)
		a -= b;
	return a;
}

void dfs(int node, int anc = -1) {
	sz[node] = 1;
	for (int to : g[node]) {
		if (to != anc && !col[to]) {
			dfs(to, node);
			sz[node] += sz[to];
		}
	}
}

int findCentroid(int node, int half, int anc = -1) {
	for (int to : g[node]) {
		if (!col[to] && to != anc && sz[to] > half)
			return findCentroid(to, half, node);
	}
	return node;
}

void solve(int node, int h = 1) {
	dfs(node);
	node = findCentroid(node, sz[node] / 2);
	col[node] = h;
	for (int to : g[node]) {
		if (!col[to])
			solve(to, h + 1);
	}
}

signed main() {
#ifdef HOME
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;

	if (m == 0) {
		cout << 1;
		return 0;
	}

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		d2[a].push_back(b);
		d2[b].push_back(a);
		d[a].insert({ f(b - a), b });
		d[b].insert({ f(a - b), a });
	}

	for (int i = 0; i < n; i++) {
		d[i].insert({ 1, f(i + 1) });
		d[i].insert({ n - 1, f(i - 1) });
		d2[i].push_back(f(i - 1));
		d2[i].push_back(f(i + 1));
	}

	vector<vector<int>> faces;

	for (int i = 0; i < n; i++) {
		while (!d[i].empty()) {
			int x = i, y = d[i].begin()->second;
			vector<int> fc;
			set<pair<int, int>> used = { *d[i].begin() };
			while (true) {
				fc.push_back(y);
				auto it = d[y].upper_bound({ f(x - y), x });
				if (it == d[y].end())
					it = d[y].begin();
				if (used.count(*it))
					break;
				x = y;
				y = it->second;
				used.insert(*it);
			}
			for (int j = 0; j < fc.size(); j++) {
				int k = j == fc.size() - 1 ? 0 : j + 1;
				d[fc[j]].erase({ f(fc[k] - fc[j]), fc[k] });
			}
			if (fc.size() == n)
				continue;
			sort(fc.rbegin(), fc.rend());
			faces.push_back(fc);
		}
	}

	sort(faces.begin(), faces.end());

	for (int i = 0; i < faces.size(); i++) {
		for (int j = 0; j < faces[i].size(); j++) {
			vector<int> v;
			for (int k = 0; k < 3; k++) {
				v.push_back({ faces[i][f(j + k, faces[i].size())] });
			}
			mp[v] = i;
		}
	}

	for (int i = 0; i < n; i++) {
		sort(all(d2[i]), [&](int x, int y) {
			return f(x - i) < f(y - i);
		});
		for (int j = 1; j < (int)d2[i].size() - 1; j++) {
			int x = mp[{d2[i][j - 1], i, d2[i][j]}],
				y = mp[{d2[i][j], i, d2[i][j + 1]}];
			g[x].push_back(y);
		}
	}

	solve(0);

	for (int i = 0; i < faces.size(); i++)
		cout << col[i] << " ";

	return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define popcount __builtin_popcount
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<bool> VB;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
typedef vector<PDD> VPD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef vector<VB> VVB;
typedef vector<VS> VVS;
typedef vector<VPI> VVPI;
typedef vector<VPL> VVPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v);
template <class T> ostream& operator<<(ostream& os, const vector<T>& v);
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
VI read_vi(int n = -1) { if (n < 0) scanf("%d", &n); VI a(n); repn(i, n) scanf("%d", &a[i]); return a; }
VL read_vl(int n = -1) { if (n < 0) scanf("%d", &n); VL a(n); repn(i, n) scanf("%lld", &a[i]); return a; }
VD read_vd(int n = -1) { if (n < 0) scanf("%d", &n); VD a(n); repn(i, n) scanf("%lf", &a[i]); return a; }
VPI read_vpi(int n = -1) { if (n < 0) scanf("%d", &n); VPI a(n); repn(i, n) scanf("%d%d", &a[i].fi,&a[i].se); return a; }
VPL read_vpl(int n = -1) { if (n < 0) scanf("%d", &n); VPL a(n); repn(i, n) scanf("%lld%lld", &a[i].fi,&a[i].se); return a; }
VPD read_vpd(int n = -1) { if (n < 0) scanf("%d", &n); VPD a(n); repn(i, n) scanf("%lf%lf", &a[i].fi,&a[i].se); return a; }
inline LL powmod(LL a, LL b, LL m) { LL r = 1; for(; b > 0; b >>= 1, a = a * a % m) { if(b & 1) r = r * a % m; } return r; }
// clang-format on
// }}}

void finalize(VVI es) {
    const int n = sz(es);
    VI ans(n, -1), size(n), ms(n), xs;
    const function<void(int, int)> dfs = [&](int x, int fa) {
        size[x] = 1, ms[x] = 0;
        xs.pb(x);
        for(int y : es[x]) {
            if(ans[y] < 0 && y != fa) {
                dfs(y, x);
                size[x] += size[y];
                setmax(ms[x], size[y]);
            }
        }
    };
    const function<void(int, int)> go = [&](int seed, int dep) {
        xs.clear();
        dfs(seed, -1);
        int mx = seed, r = 1 << 30;
        for(int x : xs) {
            int tmp = max(ms[x], size[seed] - size[x]);
            if(setmin(r, tmp)) mx = x;
        }
        ans[mx] = dep;
        for(int y : es[mx]) {
            if(ans[y] < 0) go(y, dep + 1);
        }
    };
    go(0, 1);
    repn(i, n) printf("%d ", ans[i]);
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    VVI ds(n);
    repn(i, m) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        if(a > b) swap(a, b);
        ds[a].pb(b);
    }
    repn(i, n) sort(all(ds[i]));

    vector<pair<VI, VI>> regions;
    const function<void(int, int)> extract = [&](int l, int r) {
        VI cur;
        VPI todos;
        while(l < r) {
            cur.pb(l);
            if(ds[l].empty()) {
                ++l;
            } else {
                int p = ds[l].back();
                todos.pb({l, p + 1});
                ds[l].pop_back();
                l = p;
            }
        }
        VI key = cur;
        sort(all(key), greater<int>());
        regions.pb({key, cur});
        for(const auto& p : todos) {
            extract(p.fi, p.se);
        }
    };
    extract(0, n);
    const int num = sz(regions);
    sort(all(regions));

    VVI es(num);
    map<PII, int> used;
    repn(i, num) {
        repn(k, sz(regions[i].se)) {
            int a = regions[i].se[k],
                b = regions[i].se[(k + 1) % sz(regions[i].se)];
            if(a > b) swap(a, b);
            if(used.count({a, b})) {
                int j = used[mp(a, b)];
                es[i].pb(j), es[j].pb(i);
            } else {
                used[mp(a, b)] = i;
            }
        }
    }

    finalize(es);

    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define popcount __builtin_popcount
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<bool> VB;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
typedef vector<PDD> VPD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef vector<VB> VVB;
typedef vector<VS> VVS;
typedef vector<VPI> VVPI;
typedef vector<VPL> VVPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v);
template <class T> ostream& operator<<(ostream& os, const vector<T>& v);
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
VI read_vi(int n = -1) { if (n < 0) scanf("%d", &n); VI a(n); repn(i, n) scanf("%d", &a[i]); return a; }
VL read_vl(int n = -1) { if (n < 0) scanf("%d", &n); VL a(n); repn(i, n) scanf("%lld", &a[i]); return a; }
VD read_vd(int n = -1) { if (n < 0) scanf("%d", &n); VD a(n); repn(i, n) scanf("%lf", &a[i]); return a; }
VPI read_vpi(int n = -1) { if (n < 0) scanf("%d", &n); VPI a(n); repn(i, n) scanf("%d%d", &a[i].fi,&a[i].se); return a; }
VPL read_vpl(int n = -1) { if (n < 0) scanf("%d", &n); VPL a(n); repn(i, n) scanf("%lld%lld", &a[i].fi,&a[i].se); return a; }
VPD read_vpd(int n = -1) { if (n < 0) scanf("%d", &n); VPD a(n); repn(i, n) scanf("%lf%lf", &a[i].fi,&a[i].se); return a; }
inline LL powmod(LL a, LL b, LL m) { LL r = 1; for(; b > 0; b >>= 1, a = a * a % m) { if(b & 1) r = r * a % m; } return r; }
// clang-format on
// }}}

void finalize(VVI es) {
    const int n = sz(es);
    VI ans(n, -1), size(n), ms(n), xs;
    const function<void(int, int)> dfs = [&](int x, int fa) {
        size[x] = 1, ms[x] = 0;
        xs.pb(x);
        for(int y : es[x]) {
            if(ans[y] < 0 && y != fa) {
                dfs(y, x);
                size[x] += size[y];
                setmax(ms[x], size[y]);
            }
        }
    };
    const function<void(int, int)> go = [&](int seed, int dep) {
        xs.clear();
        dfs(seed, -1);
        int mx = seed, r = 1 << 30;
        for(int x : xs) {
            int tmp = max(ms[x], size[seed] - size[x]);
            if(setmin(r, tmp)) mx = x;
        }
        ans[mx] = dep;
        for(int y : es[mx]) {
            if(ans[y] < 0) go(y, dep + 1);
        }
    };
    go(0, 1);
    repn(i, n) printf("%d ", ans[i]);
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    VVI ds(n);
    repn(i, m) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        if(a > b) swap(a, b);
        ds[a].pb(b);
    }
    repn(i, n) sort(all(ds[i]));

    vector<pair<VI, VI>> regions;
    const function<void(int, int)> extract = [&](int l, int r) {
        VI cur;
        while(l < r) {
            cur.pb(l);
            if(ds[l].empty()) {
                ++l;
            } else {
                int p = ds[l].back();
                ds[l].pop_back();
                extract(l, p + 1);
                l = p;
            }
        }
        VI key = cur;
        sort(all(key), greater<int>());
        regions.pb({key, cur});
    };
    extract(0, n);
    const int num = sz(regions);
    sort(all(regions));

    // cout << regions << endl;

    VVI es(num);
    map<PII, int> used;
    repn(i, num) {
        repn(k, sz(regions[i].se)) {
            int a = regions[i].se[k],
                b = regions[i].se[(k + 1) % sz(regions[i].se)];
            if(a > b) swap(a, b);
            if(used.count({a, b})) {
                int j = used[mp(a, b)];
                es[i].pb(j), es[j].pb(i);
            } else {
                used[mp(a, b)] = i;
            }
        }
    }

    finalize(es);

    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define popcount __builtin_popcount
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<bool> VB;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
typedef vector<PDD> VPD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef vector<VB> VVB;
typedef vector<VS> VVS;
typedef vector<VPI> VVPI;
typedef vector<VPL> VVPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v);
template <class T> ostream& operator<<(ostream& os, const vector<T>& v);
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
VI read_vi(int n = -1) { if (n < 0) scanf("%d", &n); VI a(n); repn(i, n) scanf("%d", &a[i]); return a; }
VL read_vl(int n = -1) { if (n < 0) scanf("%d", &n); VL a(n); repn(i, n) scanf("%lld", &a[i]); return a; }
VD read_vd(int n = -1) { if (n < 0) scanf("%d", &n); VD a(n); repn(i, n) scanf("%lf", &a[i]); return a; }
VPI read_vpi(int n = -1) { if (n < 0) scanf("%d", &n); VPI a(n); repn(i, n) scanf("%d%d", &a[i].fi,&a[i].se); return a; }
VPL read_vpl(int n = -1) { if (n < 0) scanf("%d", &n); VPL a(n); repn(i, n) scanf("%lld%lld", &a[i].fi,&a[i].se); return a; }
VPD read_vpd(int n = -1) { if (n < 0) scanf("%d", &n); VPD a(n); repn(i, n) scanf("%lf%lf", &a[i].fi,&a[i].se); return a; }
inline LL powmod(LL a, LL b, LL m) { LL r = 1; for(; b > 0; b >>= 1, a = a * a % m) { if(b & 1) r = r * a % m; } return r; }
// clang-format on
// }}}

void finalize(VVI es) {
    const int n = sz(es);
    VI ans(n, -1), size(n), ms(n), xs;
    const function<void(int, int)> dfs = [&](int x, int fa) {
        size[x] = 1, ms[x] = 0;
        xs.pb(x);
        for(int y : es[x]) {
            if(ans[y] < 0 && y != fa) {
                dfs(y, x);
                size[x] += size[y];
                setmax(ms[x], size[y]);
            }
        }
    };
    const function<void(int, int)> go = [&](int seed, int dep) {
        xs.clear();
        dfs(seed, -1);
        int mx = seed, r = 1 << 30;
        for(int x : xs) {
            int tmp = max(ms[x], size[seed] - size[x]);
            if(setmin(r, tmp)) mx = x;
        }
        ans[mx] = dep;
        for(int y : es[mx]) {
            if(ans[y] < 0) go(y, dep + 1);
        }
    };
    go(0, 1);
    repn(i, n) printf("%d ", ans[i]);
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    VVI ds(n);
    repn(i, m) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        if(a > b) swap(a, b);
        ds[a].pb(b);
    }
    repn(i, n) sort(all(ds[i]));

    vector<pair<VI, VI>> regions;
    const function<void(int, int)> extract = [&](int l, int r) {
        VI cur;
        VPI todos;
        while(l < r) {
            cur.pb(l);
            if(ds[l].empty()) {
                ++l;
            } else {
                int p = ds[l].back();
                todos.pb({l, p});
                ds[l].pop_back();
                l = p;
            }
        }
        cur.pb(r);
        VI key = cur;
        sort(all(key), greater<int>());
        regions.pb({key, cur});
        for(const auto& p : todos) {
            extract(p.fi, p.se);
        }
    };
    extract(0, n - 1);
    const int num = sz(regions);
    sort(all(regions));

    VVI es(num);
    map<PII, int> used;
    repn(i, num) {
        repn(k, sz(regions[i].se)) {
            int a = regions[i].se[k],
                b = regions[i].se[(k + 1) % sz(regions[i].se)];
            if(a > b) swap(a, b);
            if(used.count({a, b})) {
                int j = used[mp(a, b)];
                es[i].pb(j), es[j].pb(i);
            } else {
                used[mp(a, b)] = i;
            }
        }
    }

    finalize(es);

    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define popcount __builtin_popcount
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<bool> VB;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
typedef vector<PDD> VPD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef vector<VB> VVB;
typedef vector<VS> VVS;
typedef vector<VPI> VVPI;
typedef vector<VPL> VVPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v);
template <class T> ostream& operator<<(ostream& os, const vector<T>& v);
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
VI read_vi(int n = -1) { if (n < 0) scanf("%d", &n); VI a(n); repn(i, n) scanf("%d", &a[i]); return a; }
VL read_vl(int n = -1) { if (n < 0) scanf("%d", &n); VL a(n); repn(i, n) scanf("%lld", &a[i]); return a; }
VD read_vd(int n = -1) { if (n < 0) scanf("%d", &n); VD a(n); repn(i, n) scanf("%lf", &a[i]); return a; }
VPI read_vpi(int n = -1) { if (n < 0) scanf("%d", &n); VPI a(n); repn(i, n) scanf("%d%d", &a[i].fi,&a[i].se); return a; }
VPL read_vpl(int n = -1) { if (n < 0) scanf("%d", &n); VPL a(n); repn(i, n) scanf("%lld%lld", &a[i].fi,&a[i].se); return a; }
VPD read_vpd(int n = -1) { if (n < 0) scanf("%d", &n); VPD a(n); repn(i, n) scanf("%lf%lf", &a[i].fi,&a[i].se); return a; }
inline LL powmod(LL a, LL b, LL m) { LL r = 1; for(; b > 0; b >>= 1, a = a * a % m) { if(b & 1) r = r * a % m; } return r; }
// clang-format on
// }}}

void finalize(VVI es) {
    const int n = sz(es);
    VI ans(n, -1), size(n), ms(n), xs;
    const function<void(int, int)> dfs = [&](int x, int fa) {
        size[x] = 1, ms[x] = 0;
        xs.pb(x);
        for(int y : es[x]) {
            if(ans[y] < 0 && y != fa) {
                dfs(y, x);
                size[x] += size[y];
                setmax(ms[x], size[y]);
            }
        }
    };
    const function<void(int, int)> go = [&](int seed, int dep) {
        xs.clear();
        dfs(seed, -1);
        int mx = seed, r = 1 << 30;
        for(int x : xs) {
            int tmp = max(ms[x], size[seed] - size[x]);
            if(setmin(r, tmp)) mx = x;
        }
        ans[mx] = dep;
        for(int y : es[mx]) {
            if(ans[y] < 0) go(y, dep + 1);
        }
    };
    go(0, 1);
    repn(i, n) printf("%d ", ans[i]);
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    VVI ds(n);
    repn(i, m) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        ds[a].pb(b), ds[b].pb(a);
    }
    repn(i, n) sort(all(ds[i]));
    vector<deque<int>> ds2(n);
    repn(i, n) ds2[i] = deque<int>(all(ds[i]));

    vector<pair<VI, VI>> regions;
    int l = 0, r = n;
    while(l < r) {
        // cout << l << " " << r;
        VI cur = {l};
        while(l < r && ds2[l].empty()) {
            cur.pb(++l);
        }
        if(l < r) {
            int x = ds2[l].back();
            assert(ds2[x].front() == l);
            ds2[l].pop_back(), ds2[x].pop_front();
            replr(y, x, r) cur.pb(y);
            r = x + 1;
        } else {
            cur.pop_back();
        }
        // cout << " " << l << " " << r << " " << cur << endl;
        VI key = cur;
        sort(all(key));
        reverse(all(key));
        regions.pb({key, cur});
    }

    const int num = sz(regions);
    sort(all(regions));

    //cout << regions << endl;

    VVI es(num);
    map<PII, int> used;
    repn(i, num) {
        repn(k, sz(regions[i].se)) {
            int a = regions[i].se[k],
                b = regions[i].se[(k + 1) % sz(regions[i].se)];
            if(a > b) swap(a, b);
            if(used.count({a, b})) {
                int j = used[mp(a, b)];
                es[i].pb(j), es[j].pb(i);
            } else {
                used[mp(a, b)] = i;
            }
        }
    }

    finalize(es);

    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define popcount __builtin_popcount
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<bool> VB;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
typedef vector<PDD> VPD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef vector<VB> VVB;
typedef vector<VS> VVS;
typedef vector<VPI> VVPI;
typedef vector<VPL> VVPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
VI read_vi(int n = -1) { if (n < 0) scanf("%d", &n); VI a(n); repn(i, n) scanf("%d", &a[i]); return a; }
VL read_vl(int n = -1) { if (n < 0) scanf("%d", &n); VL a(n); repn(i, n) scanf("%lld", &a[i]); return a; }
VD read_vd(int n = -1) { if (n < 0) scanf("%d", &n); VD a(n); repn(i, n) scanf("%lf", &a[i]); return a; }
VPI read_vpi(int n = -1) { if (n < 0) scanf("%d", &n); VPI a(n); repn(i, n) scanf("%d%d", &a[i].fi,&a[i].se); return a; }
VPL read_vpl(int n = -1) { if (n < 0) scanf("%d", &n); VPL a(n); repn(i, n) scanf("%lld%lld", &a[i].fi,&a[i].se); return a; }
VPD read_vpd(int n = -1) { if (n < 0) scanf("%d", &n); VPD a(n); repn(i, n) scanf("%lf%lf", &a[i].fi,&a[i].se); return a; }
inline LL powmod(LL a, LL b, LL m) { LL r = 1; for(; b > 0; b >>= 1, a = a * a % m) { if(b & 1) r = r * a % m; } return r; }
// clang-format on
// }}}

void finalize(VVI es) {
    const int n = sz(es);
    VI ans(n, -1), size(n), ms(n), xs;
    const function<void(int, int)> dfs = [&](int x, int fa) {
        size[x] = 1, ms[x] = 0;
        xs.pb(x);
        for(int y : es[x]) {
            if(ans[y] < 0 && y != fa) {
                dfs(y, x);
                size[x] += size[y];
                setmax(ms[x], size[y]);
            }
        }
    };
    const function<void(int, int)> go = [&](int seed, int dep) {
        xs.clear();
        dfs(seed, -1);
        int mx = seed, r = 1 << 30;
        for(int x : xs) {
            int tmp = max(ms[x], size[seed] - size[x]);
            if(setmin(r, tmp)) mx = x;
        }
        ans[mx] = dep;
        for(int y : es[mx]) {
            if(ans[y] < 0) go(y, dep + 1);
        }
    };
    go(0, 1);
    repn(i, n) printf("%d ", ans[i]);
    printf("\n");
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    VVI ds(n);
    repn(i, m) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        ds[a].pb(b), ds[b].pb(a);
    }
    repn(i, n) sort(all(ds[i]));
    vector<deque<int>> ds2(n);
    repn(i, n) ds2[i] = deque<int>(all(ds[i]));

    vector<pair<VI, VI>> regions;
    int l = 0, r = n;
    while(l < r) {
        VI cur = {l};
        while(l < r && ds2[l].empty()) {
            cur.pb(++l);
        }
        if(l < r) {
            int x = ds2[l].back();
            assert(ds2[x].front() == l);
            ds2[l].pop_back(), ds2[x].pop_front();
            replr(y, x, r) cur.pb(y);
            r = x + 1;
        }
        VI key = cur;
        sort(all(key));
        reverse(all(key));
        regions.pb({key, cur});
    }

    const int num = sz(regions);
    sort(all(regions));
    VVI es(num);
    map<PII, int> used;
    repn(i, num) {
        repn(k, sz(regions[i].se)) {
            int a = regions[i].se[k],
                b = regions[i].se[(k + 1) % sz(regions[i].se)];
            if(a > b) swap(a, b);
            if(used.count({a, b})) {
                int j = used[mp(a, b)];
                es[i].pb(j), es[j].pb(i);
            } else {
                used[mp(a, b)] = i;
            }
        }
    }

    finalize(es);

    return 0;
}


#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())
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<<")"; }

const int N = 1e6 + 5;

struct CentDecomp {

  /* Start of general part */
  VVI slo;
  int n;
  VI sz, dis;
  struct Info {
    int cent, dist, subtr;
  };
  vector<vector<Info>> cents;
  vector<int> wei;
  VI col;
  CentDecomp(VVI& slo_, int n_) {
    slo = slo_;
    n = n_;
    sz.resize(n + 2);
    dis.resize(n + 2);
    cents.resize(n + 2);
    wei.resize(n + 2);
    col.resize(n + 2);
    Rec(1, n, 1);
  }

  void Rec(int v, int size, int layer) {
    v = CntSzCent(v, size, -1, 0, 0);
    debug(v, size, layer);
    dis[v] = 0;
    col[v] = layer;
    assert(layer <= 20);
    CntSzCent(v, size, -1, v, SZ(slo[v]));
    for (int i = 0; i < SZ(slo[v]); i++) {
      int nei = slo[v][i];
      DelEdge(nei, v);
      Rec(nei, sz[nei], layer + 1);
    }
  }

  int CntSzCent(int v, int size, int par, int root, int subtr) {
    sz[v] = 1;
    if (root) {
      cents[v].PB({root, dis[v], subtr});
    }
    int ret = 0;
    for (int i = 0; i < SZ(slo[v]); i++) {
      int nei = slo[v][i];
      if (v == root) {
        subtr = i;
      }
      if (par == nei) { continue; }
      dis[nei] = dis[v] + 1;
      int cnt_rec = CntSzCent(nei, size, v, root, subtr);
      sz[v] += sz[nei];
      if (cnt_rec) {
        ret = cnt_rec;
      }
    }
    if (ret == 0) {
      if (sz[v] >= size / 2) {
        return v;
      } else {
        return 0;
      }
    } else {
      return ret;
    }
  }

  void DelEdge(int v, int nei) {
    for (int i = 0; i < SZ(slo[v]); i++) {
      if (slo[v][i] == nei) {
        swap(slo[v][i], slo[v].back());
        slo[v].pop_back();
        return;
      }
    }
  }
  /* End of general part */

};VI slo1[N];
int nei[N];
int n;
int nxt[N];
int on_left[N];

//~ int Dis(int a, int b) {
  //~ if (a < b) {
    //~ return b - a;
  //~ }
  //~ return b - a + n;
//~ }
VI imp[N];
VVI slo2;
int ord[N];
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 m;
  cin>>n>>m;
  if (m == 0) {
    cout<<1<<endl;
    return 0;
  }
  RE (i, m) {
    int a, b;
    cin>>a>>b;
    slo1[a].PB(2 * i - 1);
    slo1[b].PB(2 * i);
    nei[2 * i - 1] = b;
    nei[2 * i] = a;
  }
  RE (i, n) {
    int a = i;
    int b = i + 1;
    if (i == n) {
      b = 1;
    }
    int ind = i + m;
    slo1[a].PB(2 * ind - 1);
    slo1[b].PB(2 * ind);
    nei[2 * ind - 1] = b;
    nei[2 * ind] = a;
  }
  RE (i, n) {
    sort(ALL(slo1[i]), [&](int a, int b) {
                        return nei[a] < nei[b];
                      });
    slo1[i].PB(slo1[i][0]);
    debug(i, slo1[i]);
    for (int ii = 0; ii < SZ(slo1[i]) - 1; ii++) {
      int heh = slo1[i][ii];
      if (heh % 2) {
        heh++;
      } else {
        heh--;
      }
      nxt[heh] = slo1[i][ii + 1];
    }
  }
  RE (i, 2 * (n + m)) {
    debug(i, nxt[i]);
  }
  int k = 0;
  RE (i, 2 * m) {
    if (on_left[i]) { continue; }
    k++;
    int cur = i;
    do {
      imp[k].PB(nei[cur]);
      on_left[cur] = k;
      cur = nxt[cur];
      debug(k, cur);
    } while (cur != i);
    sort(ALL(imp[k]), greater<int>());
  }
  slo2.resize(k + 2);
  RE (i, m) {
    int L = on_left[2 * i], R = on_left[2 * i - 1];
    assert(L && R);
    slo2[L].PB(R);
    slo2[R].PB(L);
  }
  assert(k - 1 == m);
  RE (i, k) {
    debug(slo2[i], imp[i]);
  }
  CentDecomp decomp(slo2, k);
  RE (i, k) {
    ord[i] = i;
  }
  sort(ord + 1, ord + k + 1, [&](int a, int b) {
                            return imp[a] < imp[b];
                            for (int ii = 0; ii < SZ(imp[a]); ii++) {
                              if (imp[a][ii] != imp[b][ii]) {
                                return imp[a][ii] < imp[b][ii];
                              }
                            }
                          });
  RE (i, k) {
    debug(i, ord[i], imp[ord[i]]);
    if (i != k) {
      debug(imp[ord[i]] < imp[ord[i + 1]]);
    }
  }
  RE (i, k) {
    //debug(ord[i]);
    cout<<decomp.col[ord[i]]<<" ";
  }
  cout<<endl;

  return 0;
}


#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())
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<<")"; }

const int N = 1e6 + 5;

struct CentDecomp {

  /* Start of general part */
  VVI slo;
  int n;
  VI sz, dis;
  struct Info {
    int cent, dist, subtr;
  };
  vector<vector<Info>> cents;
  vector<int> wei;
  VI col;
  CentDecomp(VVI& slo_, int n_) {
    slo = slo_;
    n = n_;
    sz.resize(n + 2);
    dis.resize(n + 2);
    cents.resize(n + 2);
    wei.resize(n + 2);
    col.resize(n + 2);
    Rec(1, n, 1);
  }

  void Rec(int v, int size, int layer) {
    v = CntSzCent(v, size, -1, 0, 0);
    debug(v, size, layer);
    dis[v] = 0;
    col[v] = layer;
    CntSzCent(v, size, -1, v, SZ(slo[v]));
    for (int i = 0; i < SZ(slo[v]); i++) {
      int nei = slo[v][i];
      DelEdge(nei, v);
      Rec(nei, sz[nei], layer + 1);
    }
  }

  int CntSzCent(int v, int size, int par, int root, int subtr) {
    sz[v] = 1;
    if (root) {
      cents[v].PB({root, dis[v], subtr});
    }
    int ret = 0;
    for (int i = 0; i < SZ(slo[v]); i++) {
      int nei = slo[v][i];
      if (v == root) {
        subtr = i;
      }
      if (par == nei) { continue; }
      dis[nei] = dis[v] + 1;
      int cnt_rec = CntSzCent(nei, size, v, root, subtr);
      sz[v] += sz[nei];
      if (cnt_rec) {
        ret = cnt_rec;
      }
    }
    if (ret == 0) {
      if (sz[v] >= size / 2) {
        return v;
      } else {
        return 0;
      }
    } else {
      return ret;
    }
  }

  void DelEdge(int v, int nei) {
    for (int i = 0; i < SZ(slo[v]); i++) {
      if (slo[v][i] == nei) {
        swap(slo[v][i], slo[v].back());
        slo[v].pop_back();
        return;
      }
    }
  }
  /* End of general part */

};VI slo1[N];
int nei[N];
int n;
int nxt[N];
int on_left[N];

//~ int Dis(int a, int b) {
  //~ if (a < b) {
    //~ return b - a;
  //~ }
  //~ return b - a + n;
//~ }
VI imp[N];
VVI slo2;
int ord[N];
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 m;
  cin>>n>>m;
  if (m == 0) {
    cout<<1<<endl;
    return 0;
  }
  RE (i, m) {
    int a, b;
    cin>>a>>b;
    slo1[a].PB(2 * i - 1);
    slo1[b].PB(2 * i);
    nei[2 * i - 1] = b;
    nei[2 * i] = a;
  }
  RE (i, n) {
    int a = i;
    int b = i + 1;
    if (i == n) {
      b = 1;
    }
    int ind = i + m;
    slo1[a].PB(2 * ind - 1);
    slo1[b].PB(2 * ind);
    nei[2 * ind - 1] = b;
    nei[2 * ind] = a;
  }
  RE (i, n) {
    sort(ALL(slo1[i]), [&](int a, int b) {
                        return nei[a] < nei[b];
                      });
    slo1[i].PB(slo1[i][0]);
    debug(i, slo1[i]);
    for (int ii = 0; ii < SZ(slo1[i]) - 1; ii++) {
      int heh = slo1[i][ii];
      if (heh % 2) {
        heh++;
      } else {
        heh--;
      }
      nxt[heh] = slo1[i][ii + 1];
    }
  }
  RE (i, 2 * (n + m)) {
    debug(i, nxt[i]);
  }
  int k = 0;
  RE (i, 2 * m) {
    if (on_left[i]) { continue; }
    k++;
    int cur = i;
    do {
      imp[k].PB(nei[cur]);
      on_left[cur] = k;
      cur = nxt[cur];
      debug(k, cur);
    } while (cur != i);
    sort(ALL(imp[k]), greater<int>());
  }
  slo2.resize(k + 2);
  RE (i, m) {
    int L = on_left[2 * i], R = on_left[2 * i - 1];
    assert(L && R);
    slo2[L].PB(R);
    slo2[R].PB(L);
  }
  RE (i, k) {
    debug(slo2[i], imp[i]);
  }
  CentDecomp decomp(slo2, k);
  RE (i, k) {
    ord[i] = i;
  }
  sort(ord + 1, ord + k, [&](int a, int b) {
                            for (int ii = 0; ii < SZ(imp[a]); ii++) {
                              if (imp[a][ii] != imp[b][ii]) {
                                return imp[a][ii] < imp[b][ii];
                              }
                            }
                          });
  RE (i, k) {
    //debug(ord[i]);
    cout<<decomp.col[ord[i]]<<" ";
  }
  cout<<endl;

  return 0;
}


#include<cstdio>
#include<algorithm>
#include<vector>
#define pii pair<int,int>
using namespace std;
int n, m, cc, cnt, AL;
vector<pii>E[101000];
vector<int>G[201000], F[201000];
int Num[501000], Col[201000];
void Go(int b, int e){
    G[cnt].push_back(e);
    int t = lower_bound(E[e].begin(),E[e].end(), pii(b,0)) - E[e].begin();
    pii tp = E[e][(t+1)%E[e].size()];
    if(Num[tp.second])return;
    Num[tp.second] = cnt;
    Go(e, tp.first);
}
int chk[201000], C[201000];
void DFS(int a, int pp){
    int i, x;
    C[a] = 1;
    for(i=0;i<F[a].size();i++){
        x = F[a][i];
        if(chk[x] || x==pp)continue;
        DFS(x, a);
        C[a] += C[x];
    }
}
int DFS2(int a, int pp, int MM){
    int i, x;
    for(i=0;i<F[a].size();i++){
        x = F[a][i];
        if(chk[x] || x==pp)continue;
        if(C[x] * 2 > MM)return DFS2(x, a, MM);
    }
    return a;
}
int get_mid(int a){
    DFS(a,0);
    if(C[a]==1)return 0;
    return DFS2(a,0,C[a]);
}
void Do(int a, int dep){
    int mid = get_mid(a);
    if(!mid){
        Col[a] = dep;
        return;
    }
    Col[mid] = dep;
    int i;
    chk[mid] = 1;
    for(i=0;i<F[mid].size();i++){
        if(!chk[F[mid][i]]) Do(F[mid][i], dep+1);
    }
    chk[mid] = 0;
}
struct AA{
    long long g;
    int num;
    bool operator<(const AA &p)const{
        return g<p.g;
    }
}ord[201000];
int main(){
    int i, a, b, j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        E[a].push_back(pii(b,cc++));
        E[b].push_back(pii(a,cc++));
    }
    for(i=1;i<=n;i++){
        E[i].push_back(pii(i%n+1,cc++));
        E[i%n+1].push_back(pii(i,cc++));
    }
    for(i=1;i<=n;i++){
        sort(E[i].begin(),E[i].end());
    }
    for(i=1;i<=n;i++){
        for(j=0;j<E[i].size();j++){
            if(!Num[E[i][j].second]){
                cnt++;
                Num[E[i][j].second] = cnt;
                Go(i,E[i][j].first);
            }
        }
    }
    for(i=1;i<=cnt;i++){
        if(G[i].size() == n && !AL)AL = i;
    }
    for(i=0;i<cc;i++){
        if(Num[i]!=AL && Num[i^1]!=AL)F[Num[i]].push_back(Num[i^1]);
    }
    int rt = 1;
    if(AL==1)rt++;
    Do(rt, 1);
    int ccc = 0;
    for(i=1;i<=cnt;i++){
        if(i==AL)continue;
        sort(G[i].begin(),G[i].end());
        long long ss = 0;
        for(j=0;j<2;j++){
            ss *= 1000000;
            ss += G[i][G[i].size()-j-1];
        }
        ord[ccc++]={ss,i};
    }
    sort(ord,ord+ccc);
    for(i=0;i<ccc;i++){
        printf("%d ",Col[ord[i].num]);
    }
}