/*
    n<=10^9个位置, q<=10^5个操作
    操作有三种
    (1)插入
    选择靠右的最长空白的一段,然后插入到中间(若长度为偶数,是指靠右的那个中间位置)
    (2)删除
    (3)查询一段中的已插入点个数

    我一开始想线段树,搞不出,主要是那些点不确定
    看了shik的代码,神奇丫

    树状数组的数组可以用map<int,int>来做,解决了空间问题!!!
    用set<Segment>来存储可用的线段
    然后需要再加多一个set记录所有分割点,这个很重要,我当时没想到这个#_#

    然后就是维护上面3个主要的数据结构了
*/

#include
<iostream>
#include
<cstring>
#include
<map>
#include
<algorithm>
#include
<stack>
#include
<queue>
#include
<cmath>
#include
<string>
#include
<cstdlib>
#include
<vector>
#include
<cstdio>
#include
<set>
#include
<list>
#include
<numeric>
#include
<cassert>
#include
<ctime>
#include
<bitset>

using namespace std;

struct Segment {
    
int st, ed;
    Segment(
int st, int ed) : st(st), ed(ed){
    }

}
;

inline 
bool operator < (const Segment & A, const Segment &B) {
    
if(A.ed - A.st != B.ed - B.st) {
        
return A.ed - A.st > B.ed - B.st;
    }

    
return A.st > B.st;
}


map
<intint> C;
int n, q;

inline 
int lowbit(int x) {
    
return x & (-x);
}


void insert(int x , int val) {
    
while(x <= n) {
        C[x] 
+= val;
        x 
+= lowbit(x);
    }

}


int query(int x) {
    map
<int,int>::iterator it;
    
int ans = 0;
    
while(x > 0{
        
//    ans += C[x];  不要直接这样,需要先查找一下,不存在的不用加,快很多!!!
        if((it = C.find(x)) != C.end()){
            ans 
+= it->second;
        }

        x 
-= lowbit(x);
    }

    
return ans;
}


int query(int x, int y) {
    
return query(y) - query(x-1);
}


int main()
{
#ifndef ONLINE_JUDGE
    freopen(
"in","r",stdin);
#endif
    
    
for (; ~scanf("%d%d"&n, &q); ) {
        C.clear();
        
set<Segment> iset;
        iset.insert(Segment(
1,n));
        
set<int> pt;
        pt.insert(
0);
        pt.insert(n
+1);
        map
<int,int> mp;

        
int p, st, ed;
        
while(q--{
            scanf(
"%d"&p);
            
if(p == 0{
                scanf(
"%d%d"&st, &ed);
                printf(
"%d\n", query(st,ed));
            }
 else {
                
if(mp[p] == 0){
                    
set<Segment>::iterator it = iset.begin();
                    st 
= it->st, ed = it->ed;
                    iset.erase(it);
                    
int m = (st+ed+1/ 2;
                    mp[p] 
= m;
                    pt.insert(m);
                    insert(m,
1);
                    
if(st <= m - 1){
                        iset.insert(Segment(st,m
-1));
                    }

                    
if(m+1 <= ed) {
                        iset.insert(Segment(m
+1,ed));
                    }

                }
 else {
                    
int m = mp[p];
                    mp[p] 
= 0;
                    
set<int>::iterator left, right, it;
                    
/*
                        left = pt.lower_bound(m);
                        left--;
                        right = pt.upper_bound(m);
                        pt.erase(m);
                    
*/

                    left 
= right = it = pt.find(m);
                    left 
--;
                    right
++;
                    pt.erase(it);
                    insert(m,
-1);
                    st 
= (*left)+1;
                    ed 
= (*right)-1;
                    
if(st <= m - 1{
                        iset.erase(Segment(st, m
-1));
                    }

                    
if(m+1 <= ed) {
                        iset.erase(Segment(m
+1,ed));
                    }

                    
if(st <= ed){
                        iset.insert(Segment(st,ed));
                    }

                }

            }

        }

    }

    
return 0;
}