#include <stdio.h>
#include <algorithm>

using namespace std;

int dokleLEVO [510], dokleDOLE [510], dokleGORE [510], dokleDESNO [510]; // dokle je stigla "pukotina"
bool oDOLE [510][510], oGORE [510][510], oLEVO [510][510], oDESNO [510][510];
long long S [510][510]; // suma od (1,1) do (i,j)
int broj [510];
int rbgrupe [510][510];
int trenX [510][510], trenY [510][510]; // gde je gornje levo polje
long long Sume [510][510], tmpSume [510][510]; // [i][j] - sortirano u rastujem (i-ti red, j-ti po velicini)
int n, q, a, b, op;
long long l, h;
int k;
int levo, desno, levagr, desnagr;

FILE *in = fopen ("mrvice.in", "r");
FILE *out = fopen ("mrvice.out", "w");

int main ()
{
    fscanf (in, "%d %d", &n, &q);
    for (int i = 0; i <= n + 1; i++)
    {
        S [0][i] = 0;
        S [i][0] = 0;
        S [n + 1][i] = 0;
        S [i][n + 1] = 0;
    }
    for (int j = 1; j <= n; j++)
        for (int i = 1; i <= n; i++)
        {
            fscanf (in, "%lld", &S [i][j]);
            S [i][j] = S [i][j] + S [i - 1][j] + S [i][j - 1] - S [i - 1][j - 1];
        }
    for (int i = 1; i <= n; i++)
    {
        oGORE [i][1] = true;
        oDOLE [i][n] = true;
        oLEVO [n][1] = true;
        oDESNO [n][i] = true;
        dokleGORE [i] = 1;
        dokleDOLE [i] = n + 1;
        dokleLEVO [i] = 1;
        dokleDESNO [i] = n + 1;
    }
    broj [n] = 1;
    Sume [n][n] = S [n][n];
    rbgrupe [n][n] = 1;
    trenX [n][n] = 1;
    trenY [n][n] = 1;
    for (int j = 1; j <= q; j++)
    {
        fscanf (in, "%d", &op);
        if (op == 1)
        {
            fscanf (in, "%d %d", &a, &b);

            if (a == 0 && dokleGORE [b] != n + 1)
            {
                k = dokleGORE [b];
                while (!oDOLE [b][k] && !oDOLE [b + 1][k])
                {
                    oDESNO [b][k] = true;
                    oLEVO [b + 1][k] = true;
                    k++;
                }
                oDESNO [b][k] = true;
                oLEVO [b + 1][k] = true;
                int p = b + 1;
                int t = dokleGORE [b] - 1;
                while (!oDESNO [p][k])
                    p++;
                Sume [k][rbgrupe [p][k]] = S [p][k] - S [p][t] - S [b][k] + S [b][t];
                broj [k]++;
                trenX [b][k] = trenX [p][k];
                trenY [b][k] = trenY [p][k];
                trenX [p][k] = b + 1;
                trenY [p][k] = dokleGORE [b];
                Sume [k][broj [k]] = S [b][k] - S [trenX [b][k] - 1][k] - S [b][trenY [b][k] - 1] +
                    S [trenX [b][k] - 1][trenY [b][k] - 1];
                rbgrupe [b][k] = broj [k];
                dokleGORE [b] = k + 1;
                if (dokleGORE [b] == dokleDOLE [b])
                {
                    dokleGORE [b] = n + 1;
                    dokleDOLE [b] = 1;
                }
                for (int i = 1; i <= broj [k]; i++)
                    tmpSume [k][i] = Sume [k][i];
                sort (tmpSume [k] + 1, tmpSume [k] + broj [k] + 1);
            }

            if (a == 1 && dokleDESNO [b] != 1)
            {
                k = dokleDESNO [b];
                do
                {
                    oDOLE [k][b] = true;
                    oGORE [k][b + 1] = true;
                    k--;
                }
                while (!oLEVO [k][b] && !oLEVO [k][b + 1]);
                oDOLE [k][b] = true;
                oGORE [k][b + 1] = true;
                int p = b + 1;
                int t = dokleDESNO [b] - 1;
                while (!oDOLE [t][p])
                    p++;
                Sume [p][rbgrupe [t][p]] =
                    S [t][p] - S [t][k - 1] - S [b][k - 1] + S [b][k - 1];
                broj [b]++;
                trenX [t][b] = trenX [t][p];
                trenY [t][b] = trenY [t][p];
                trenX [t][p] = k;
                trenY [t][p] = b + 1;
                Sume [b][broj [b]] =
                    S [t][b] - S [t][trenY [t][b] - 1] - S [trenX [t][b] - 1][b] +
                        S [trenX [t][b] - 1][trenY [t][b] - 1];
                dokleGORE [b] = k;
                rbgrupe [t][p] = broj [b];
                if (dokleDESNO [b] == dokleLEVO [b])
                {
                    dokleLEVO [b] = n + 1;
                    dokleDESNO [b] = 1;
                }
                for (int i = 1; i <= broj [b]; i++)
                    tmpSume [b][i] = Sume [b][i];
                for (int i = 1; i <= broj [p]; i++)
                    tmpSume [p][i] = Sume [p][i];
                sort (Sume [b] + 1, Sume [b] + broj [b] + 1);
                sort (Sume [p] + 1, Sume [p] + broj [p] + 1);
            }

            if (a == 2 && dokleDOLE [b] != 1)
            {
                k = dokleDOLE [b];
                do
                {
                    oDESNO [b][k] = true;
                    oLEVO [b + 1][k] = true;
                    k--;
                }
                while (!oGORE [b][k] && !oGORE [b + 1][k]);
                oDESNO [b][k] = true;
                oLEVO [b + 1][k] = true;
                int p = b + 1;
                int t = dokleDOLE [b] - 1;
                while (!oDESNO [p][t])
                    p++;
                Sume [t][rbgrupe [p][t]] =
                    S [p][t] - S [p][k - 1] - S [b][t] + S [b][k - 1];
                broj [t]++;
                trenX [b][t] = trenX [p][t];
                trenY [b][t] = trenY [p][t];
                trenX [p][t] = b + 1;
                trenY [p][t] = k;
                Sume [t][broj [t]] =
                    S [b][t] - S [trenX [b][t] - 1][t] - S [b][trenY [b][t] - 1] +
                        S [trenX [b][t] - 1][trenY [b][t] - 1];
                rbgrupe [b][t] = broj [t];
                dokleDOLE [b] = k;
                if (dokleGORE [b] == dokleDOLE [b])
                {
                    dokleGORE [b] = n + 1;
                    dokleDOLE [b] = 1;
                }
                for (int i = 1; i <= broj [t]; i++)
                    tmpSume [t][i] = Sume [t][i];
                sort (tmpSume [t] + 1, tmpSume [t] + broj [t] + 1);
            }

            if (a == 3 && dokleLEVO [b] != n + 1)
            {
                k = dokleLEVO [b];
                while (!oDESNO [k][b] && !oDESNO [k][b + 1])
                {
                    oDOLE [k][b] = true;
                    oGORE [k][b + 1] = true;
                    k++;
                }
                oDOLE [k][b] = true;
                oGORE [k][b + 1] = true;
                int p = b + 1;
                int t = dokleLEVO [b] - 1;
                while (!oDOLE [k][p])
                    p++;
                Sume [p][rbgrupe [k][p]] =
                    S [k][p] - S [k][b] - S [t][p] + S [t][b];
                broj [b]++;
                trenX [k][b] = trenX [k][p];
                trenY [k][b] = trenY [k][p];
                trenX [k][p] = dokleDESNO [b];
                trenY [k][p] = b + 1;
                Sume [b][broj [b]] =
                    S [k][b] - S [k][trenY [k][b] - 1] - S [trenX [k][b] - 1][b] +
                        S [trenX [k][b] - 1][trenY [k][b] - 1];

                rbgrupe [k][b] = broj [b];
                dokleLEVO [b] = k + 1;
                if (dokleDESNO [b] == dokleLEVO [b])
                {
                    dokleLEVO [b] = n + 1;
                    dokleDESNO [b] = 1;
                }
                for (int i = 1; i <= broj [b]; i++)
                    tmpSume [b][i] = Sume [b][i];
                for (int i = 1; i <= broj [p]; i++)
                    tmpSume [p][i] = Sume [p][i];
                sort (Sume [b] + 1, Sume [b] + broj [b] + 1);
                sort (Sume [p] + 1, Sume [p] + broj [p] + 1);
            }

        }
        else
        {
            fscanf (in, "%d %d", &l, &h);
            k = 0;
            for (int i = 1; i <= n; i++)
            {
                levo = 1; desno = broj [i];
                while (desno - levo > 1)
                {
                    if (Sume [i][(levo + desno) / 2] < l)
                        levo = (levo + desno) / 2;
                    else
                        if (Sume [i][(levo + desno) / 2] > l)
                            desno = (levo + desno) / 2;
                        else
                        {
                            levo = (levo + desno) / 2;
                            desno = levo;
                        }
                }
                if (Sume [i][levo] >= l)
                    levagr = levo;
                else
                    levagr = desno;
                levo = 1; desno = broj [i];
                while (desno - levo > 1)
                {
                    if (Sume [i][(levo + desno) / 2] < h)
                        levo = (levo + desno) / 2;
                    else
                        if (Sume [i][(levo + desno) / 2] > h)
                            desno = (levo + desno) / 2;
                        else
                        {
                            levo = (levo + desno) / 2;
                            desno = levo;
                        }
                }
                if (Sume [i][desno] <= h)
                    desnagr = desno;
                else
                    desnagr = levo;
                k += desnagr - levagr + 1;
            }
            fprintf (out, "%d\n", k);
        }
    }
    return 0;
}
