#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
// Struktura DSU do łączenia przedziałów czasowych
struct DSU {
vector<int> parent;
vector<ll> length;
ll T;
ll total_starts;
DSU(int n, ll t) : T(t), total_starts(0) {
parent.resize(n);
length.assign(n, 0);
for(int i=0; i<n; ++i) parent[i] = i;
}
int find(int i) {
if (parent[i] == i) return i;
return parent[i] = find(parent[i]);
}
// Funkcja obliczająca ile startów mieści się w bloku o długości L
ll f(ll L) {
return max(0LL, L - T + 1);
}
void activate(int i, ll len) {
length[i] = len;
total_starts += f(len);
}
void unite(int i, int j) {
int root_i = find(i);
int root_j = find(j);
if (root_i != root_j) {
total_starts -= f(length[root_i]);
total_starts -= f(length[root_j]);
parent[root_i] = root_j;
length[root_j] += length[root_i];
total_starts += f(length[root_j]);
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
ll t, d;
if (!(cin >> n >> t >> d)) return 0;
map<ll, int> diff;
for (int i = 0; i < n; ++i) {
ll a, b;
cin >> a >> b;
diff[a]++;
diff[b + 1]--;
}
// Dodanie granic obszaru ucieczki [1, D]
if (diff.find(1) == diff.end()) diff[1] = 0;
if (diff.find(d + 1) == diff.end()) diff[d + 1] = 0;
vector<pair<ll, int>> points(diff.begin(), diff.end());
vector<pair<int, ll>> intervals;
int current_v = 0;
for (int i = 0; i < (int)points.size() - 1; ++i) {
current_v += points[i].second;
ll start = points[i].first;
ll end = points[i + 1].first;
if (start > d) break;
ll actual_end = min(d + 1, end);
if (actual_end > start) {
intervals.push_back({current_v, actual_end - start});
}
}
int m = intervals.size();
vector<vector<int>> val_to_idx(n + 1);
for (int i = 0; i < m; ++i) {
if (intervals[i].first <= n)
val_to_idx[intervals[i].first].push_back(i);
}
DSU dsu(m, t);
vector<bool> active(m, false);
vector<ll> results(n + 1, 0);
// Idziemy od największego k, aby budować k-bezpieczeństwo
for (int k = n; k >= 1; --k) {
for (int idx : val_to_idx[k]) {
active[idx] = true;
dsu.activate(idx, intervals[idx].second);
if (idx > 0 && active[idx - 1]) dsu.unite(idx, idx - 1);
if (idx < m - 1 && active[idx + 1]) dsu.unite(idx, idx + 1);
}
results[k] = dsu.total_starts;
}
if (d >= t) results[0] = d - t + 1;
for (int k = 0; k <= n; ++k) {
if (results[k] > 0) {
cout << k << " " << results[k] << "\n";
}
}
return 0;
}