#include <fstream>
#include <algorithm>
using namespace std;
ifstream f("marbles.in");
ofstream g("marbles.out");
int n, m, x, culoare, v, y, culori[100005];
struct cv
{
int fr[65] = {0};
int maxFr;
};
cv aint[300005];
inline void build(int nod, int L, int R)
{
if (L == R) {
aint[nod].fr[culori[L]] = 1;
aint[nod].maxFr = 1;
return;
}
int mij = (L + R) / 2;
build(nod << 1, L, mij);
build(nod << 1 | 1, mij + 1, R);
for (int i = 1; i <= 64; ++i) {
aint[nod].fr[i] = aint[nod << 1].fr[i] + aint[nod << 1 | 1].fr[i];
}
aint[nod].maxFr = max(aint[nod << 1].maxFr, aint[nod << 1 | 1].maxFr);
}
inline void updateAint(int nod, int L, int R, int x, int culoareVeche, int culoareNoua)
{
if (L == R) {
aint[nod].fr[culoareVeche]--;
aint[nod].fr[culoareNoua]++;
aint[nod].maxFr = *max_element(aint[nod].fr, aint[nod].fr + 65);
return;
}
int mij = (L + R) / 2;
if (x <= mij) {
updateAint(nod << 1, L, mij, x, culoareVeche, culoareNoua);
}
else {
updateAint(nod << 1 | 1, mij + 1, R, x, culoareVeche, culoareNoua);
}
aint[nod].maxFr = max(aint[nod << 1].maxFr, aint[nod << 1 | 1].maxFr);
}
inline void searchAint(int nod, int L, int R, int x, int y, int &ans)
{
if (x > R || y < L) {
return;
}
if (x <= L && R <= y) {
ans = max(ans, aint[nod].maxFr);
return;
}
int mij = (L + R) / 2;
if (x <= mij) {
searchAint(nod << 1, L, mij, x, y, ans);
}
if (y > mij) {
searchAint(nod << 1 | 1, mij + 1, R, x, y, ans);
}
}
int main()
{
f >> n >> m;
for (int i = 1; i <= n; ++i) {
int a, b;
f >> a >> b;
culori[a] = b;
}
build(1, 1, n);
for (int i = 1; i <= m; ++i) {
f >> v >> x >> y;
if (v == 0) {
int vechi = culori[x];
culori[x + y] = culori[x];
culori[x] = 0;
updateAint(1, 1, n, x + y, vechi, culori[x + y]);
}
else {
int ans = 0;
searchAint(1, 1, n, x, y, ans);
g << ans << '\n';
}
}
return 0;
}