#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<int> x(M), y(M);
// For each participant, list of matches they participate in (sorted by day)
vector<vector<int>> matches(N);
for(int i = 0; i < M; i++){
cin >> x[i] >> y[i];
matches[x[i]].push_back(i);
matches[y[i]].push_back(i);
}
// Build tree: parent[i] = next match where winner x[i] participates, or M (fake root)
// For each participant, we need a pointer to find the next match after a given one.
// We can use upper_bound on the sorted matches list.
vector<int> par(M);
vector<vector<int>> children(M + 1); // M is the fake root
for(int i = 0; i < M; i++){
int w = x[i]; // winner of match i
auto &ml = matches[w];
// Find next match of w after day i
auto it = upper_bound(ml.begin(), ml.end(), i);
if(it == ml.end()){
par[i] = M; // fake root
} else {
par[i] = *it;
}
children[par[i]].push_back(i);
}
// span[i] = par[i] - i (par[i] is either a day number or M)
// When par[i] = M, span[i] = M - i
// Otherwise span[i] = par[i] - i
// DFS from fake root (node M)
// Maintain cnt[p] for each participant p
// Use a set<pair<int,int>> storing (-cnt, p) for efficient max query
// (We only insert/remove entries with nonzero cnt)
vector<int> cnt(N, 0);
set<pair<int,int>> S; // (-cnt[p], p) for participants with cnt[p] > 0
vector<int> medal_winner(M);
// Iterative DFS to avoid stack overflow
// We use a stack of (node, child_index, entered)
// When we first visit a node, we "enter" it (add span to cnt)
// Then we process its children one by one
// When all children are done, we "leave" it (subtract span from cnt)
// Actually, let's use a different iterative DFS approach:
// Push (node, false) initially.
// When popped with false: push (node, true), then push all children (child, false).
// When popped with true: this is the "leave" step.
// But we need to process the medal right after entering.
// Better: explicit stack with state
struct Frame {
int node;
int childIdx;
};
stack<Frame> stk;
// Start from fake root's children
// The fake root doesn't correspond to a match, so we handle it specially
for(int c : children[M]){
stk.push({c, -1}); // -1 means not yet entered
}
// We need to reverse the order so that children are processed in the right order
// Actually, order doesn't matter for correctness
// Hmm, the above won't work well because we push all root's children at once.
// Let me use a cleaner iterative DFS.
// Use a stack of (node, phase)
// phase 0: enter (add span, process medal, then push children)
// phase 1: leave (subtract span)
stack<pair<int,int>> dfs_stack;
for(int i = (int)children[M].size()-1; i >= 0; i--){
dfs_stack.push({children[M][i], 0});
}
while(!dfs_stack.empty()){
auto [node, phase] = dfs_stack.top();
dfs_stack.pop();
if(phase == 0){
// Enter node
int w = x[node];
int span = par[node] - node;
// Update cnt and set
if(cnt[w] > 0){
S.erase({-cnt[w], w});
}
cnt[w] += span;
S.insert({-cnt[w], w});
// Process medal for this node
// The winner of medal 'node' is the participant with max cnt (smallest index on tie)
auto it = S.begin();
medal_winner[node] = it->second;
// Push leave marker
dfs_stack.push({node, 1});
// Push children (in reverse order so they're processed in order)
auto &ch = children[node];
for(int i = (int)ch.size()-1; i >= 0; i--){
dfs_stack.push({ch[i], 0});
}
} else {
// Leave node
int w = x[node];
int span = par[node] - node;
S.erase({-cnt[w], w});
cnt[w] -= span;
if(cnt[w] > 0){
S.insert({-cnt[w], w});
}
}
}
// Count medals per participant
vector<int> ans(N, 0);
for(int i = 0; i < M; i++){
ans[medal_winner[i]]++;
}
for(int i = 0; i < N; i++){
cout << ans[i];
if(i + 1 < N) cout << ' ';
}
cout << '\n';
return 0;
}