/*
    Aleksandar "Al3kSaNdaR" Ivanovic

    mrvice
*/
#include <cstdio>
#include <algorithm>
#include <iostream>

using namespace std;

typedef long long int lld;

const int MaxN = 500 + 5;

int N, M;

lld BIT[MaxN][MaxN];

inline void Update ( int idx, int idy, lld Value )
{
    while ( idx <= N )
    {
        int _idy = idy;

        while ( _idy <= N )
        {
            BIT[idx][_idy] += Value;

            _idy += _idy & -_idy;
        }

        idx += idx & -idx;
    }
}

inline lld Get ( int idx, int idy )
{
    lld Ret = 0LL;

    while ( idx > 0 )
    {
        int _idy = idy;

        while ( _idy > 0 )
        {
            Ret += BIT[idx][_idy];

            _idy -= _idy & -_idy;
        }

        idx -= idx & -idx;
    }

    return Ret;
}

inline lld Query ( int X1, int Y1, int X2, int Y2 )
{
    X1--;
    Y1--;

    lld Ret = 0LL;

    Ret += Get ( X2, Y2 );
    Ret -= Get ( X1, Y2 );
    Ret -= Get ( X2, Y1 );
    Ret += Get ( X1, Y1 );

    return Ret;
}

typedef struct Rect
{
    int X1, Y1, X2, Y2;

    Rect ( void )
    {
    };

    Rect ( int _X1, int _Y1, int _X2, int _Y2 )
    {
        X1 = _X1;
        Y1 = _Y1;
        X2 = _X2;
        Y2 = _Y2;
    }

    inline void Print ( void )
    {
        cout << X1 << " " << Y1 << " " << X2 << " " << Y2 << endl;
    }

    inline bool operator == ( const Rect & NewRect )
    {
        return ( ( X1 == NewRect.X1 ) && ( Y1 == NewRect.Y1 ) && ( X2 == NewRect.X2 ) && ( Y2 == NewRect.Y2 ) );
    }
};

int RectsSize = 0, LastPosTB[MaxN], LastPosBT[MaxN], LastPosLR[MaxN], LastPosRL[MaxN];

Rect Rects[MaxN * MaxN];

inline bool Ok ( const Rect & NewRect )
{
    if ( ( NewRect.X1 < 1 ) || ( NewRect.X1 > N ) ) return false;
    if ( ( NewRect.Y1 < 1 ) || ( NewRect.Y1 > N ) ) return false;
    if ( ( NewRect.X2 < 1 ) || ( NewRect.X2 > N ) ) return false;
    if ( ( NewRect.Y2 < 1 ) || ( NewRect.Y2 > N ) ) return false;

    if ( ! ( ( NewRect.X1 <= NewRect.X2 ) && ( NewRect.Y1 <= NewRect.Y2 ) ) ) return false;

    return true;
}

int main ( void )
{
    //freopen ( "mrvice.in", "r", stdin );
    //freopen ( "mrvice.out", "w", stdout );

    scanf ( "%d %d", &N, &M );

    for ( int i = 1; i <= N; i++ )
        for ( int j = 1; j <= N; j++ )
        {
            lld Value;

            scanf ( "%lld", &Value );

            Update ( i, j, Value );
        }

    for ( int i = 1; i <= N; i++ )
    {
        LastPosTB[i] = 1;
        LastPosBT[i] = N;
        LastPosLR[i] = 1;
        LastPosRL[i] = N;
    }

    Rects[RectsSize++] = Rect ( 1, 1, N, N );

    for ( int i = 0; i < M; i++ )
    {
        int Command;

        scanf ( "%d", &Command );

        if ( Command == 1 )
        {
            int Direction, Pos;

            scanf ( "%d %d", &Direction, &Pos );

            int idx = -1;

            Rect TempRect, Cut1, Cut2;

            if ( Direction == 0 )
            {
                for ( int j = 0; j < RectsSize; j++ )
                {
                    if ( LastPosTB[Pos] != Rects[j].X1 ) continue;

                    if ( ( Rects[j].Y1 <= Pos ) && ( Pos <= Rects[j].Y2 ) )
                    {
                        idx = j;

                        break;
                    }
                }

                TempRect = Rects[idx];

                Cut1 = Rect ( TempRect.X1, TempRect.Y1, TempRect.X2, Pos );

                Cut2 = Rect ( TempRect.X1, Pos + 1, TempRect.X2, TempRect.Y2 );

                if ( ( ! Ok ( Cut1 ) ) || ( ! Ok ( Cut2 ) ) ) continue;

                Rects[idx] = Cut1;
                Rects[RectsSize++] = Cut2;

                LastPosTB[Pos] = TempRect.X2 + 1;

                continue;
            }

            if ( Direction == 1 )
            {
                for ( int j = 0; j < RectsSize; j++ )
                {
                    if ( LastPosRL[Pos] != Rects[j].Y2 ) continue;

                    if ( ( Rects[j].X1 <= Pos ) && ( Pos <= Rects[j].X2 ) )
                    {
                        idx = j;

                        break;
                    }
                }

                TempRect = Rects[idx];

                Cut1 = Rect ( TempRect.X1, TempRect.Y1, Pos, TempRect.Y2 );

                Cut2 = Rect ( Pos + 1, TempRect.Y1, TempRect.X2, TempRect.Y2 );

                if ( ( ! Ok ( Cut1 ) ) || ( ! Ok ( Cut2 ) ) ) continue;

                Rects[idx] = Cut1;
                Rects[RectsSize++] = Cut2;

                LastPosRL[Pos] = TempRect.Y1 - 1;

                continue;
            }

            if ( Direction == 2 )
            {
                for ( int j = 0; j < RectsSize; j++ )
                {
                    if ( LastPosBT[Pos] != Rects[j].X2 ) continue;

                    if ( ( Rects[j].Y1 <= Pos ) && ( Pos <= Rects[j].Y2 ) )
                    {
                        idx = j;

                        break;
                    }
                }

                TempRect = Rects[idx];

                Cut1 = Rect ( TempRect.X1, TempRect.Y1, TempRect.X2, Pos );

                Cut2 = Rect ( TempRect.X1, Pos + 1, TempRect.X2, TempRect.Y2 );

                if ( ( ! Ok ( Cut1 ) ) || ( ! Ok ( Cut2 ) ) ) continue;

                Rects[idx] = Cut1;
                Rects[RectsSize++] = Cut2;

                LastPosBT[Pos] = TempRect.X1 - 1;

                continue;
            }

            if ( Direction == 3 )
            {
                for ( int j = 0; j < RectsSize; j++ )
                {
                    if ( LastPosLR[Pos] != Rects[j].Y1 ) continue;

                    if ( ( Rects[j].X1 <= Pos ) && ( Pos < Rects[j].X2 ) )
                    {
                        idx = j;

                        break;
                    }
                }

                TempRect = Rects[idx];

                Cut1 = Rect ( TempRect.X1, TempRect.Y1, Pos, TempRect.Y2 );

                Cut2 = Rect ( Pos + 1, TempRect.Y1, TempRect.X2, TempRect.Y2 );

                if ( ( ! Ok ( Cut1 ) ) || ( ! Ok ( Cut2 ) ) ) continue;

                Rects[idx] = Cut1;
                Rects[RectsSize++] = Cut2;

                LastPosLR[Pos] = TempRect.Y2 + 1;

                continue;
            }

            continue;
        }

        if ( Command == 2 )
        {
            lld L, H;

            scanf ( "%lld %lld", &L, &H );

            int Cnt = 0;

            for ( int j = 0; j < RectsSize; j++ )
            {
                lld Sum = Query ( Rects[j].X1, Rects[j].Y1, Rects[j].X2, Rects[j].Y2 );

                if ( ( L <= Sum ) && ( Sum <= H ) ) Cnt++;
            }

            printf ( "%d\n", Cnt );

            continue;
        }
    }

    return 0;
}
