#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
inline int read() {
int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}
const int N = 500005;
int disc[N];
struct OPT{ int opt, l, r; } A[N];
struct Bit{
int sum[N], n;
void update(int p,int v) { p ++;
for (; p <= n; p += (p & (-p))) sum[p] += v;
}
int query(int p) { p ++;
int ans = 0;
for (; p; p -= (p & (-p))) ans += sum[p];
return ans;
}
}bit;
void solve1(int n,int k) {
bit.n = n + 2; int now = 0;
for (int i = 1; i <= n; ++i) {
int opt = read(), l = read(), r, v;
if (opt == 3) { printf("%d\n", bit.query(l % k) + now); continue; }
r = read();
v = opt == 1 ? 1 : -1;
if (r - l + 1 >= k) { now += v; continue; }
l %= k, r %= k;
if (l <= r) bit.update(l, v), bit.update(r + 1, -v);
else bit.update(0, v), bit.update(r + 1, -v), bit.update(l, v), bit.update(k, -v);
}
}
void solve0(int n) {
int tot = 0, cnt = 1;
for (int i = 1; i <= n; ++i) {
A[i].opt = read(), A[i].l = read(); A[i].r = -1;
disc[++tot] = A[i].l;
if (A[i].opt <= 2) A[i].r = read(), disc[++tot] = A[i].r;
}
sort(disc + 1, disc + tot + 1);
for (int i = 2; i <= tot; ++i) if (disc[i] != disc[cnt]) disc[++cnt] = disc[i];
bit.n = cnt + 2;
for (int i = 1; i <= n; ++i) {
A[i].l = lower_bound(disc + 1, disc + cnt + 1, A[i].l) - disc;
if (A[i].r != -1) A[i].r = lower_bound(disc + 1, disc + cnt + 1, A[i].r) - disc;
if (A[i].opt == 1) bit.update(A[i].l, 1), bit.update(A[i].r + 1, -1);
else if (A[i].opt == 2) bit.update(A[i].l, -1), bit.update(A[i].r + 1, 1);
else printf("%d\n", bit.query(A[i].l));
}
}
int main() {
int n = read(), k = read();
if (!n && !k) { cout << "fafa"; return 0; }
if (k == 0) solve0(n);
else solve1(n, k);
return 0;
}