/*
    Aleksandar "Al3kSaNdaR" Ivanovic

    pijaca
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>

using namespace std;

const int MaxN = 50000 + 5;
const int MaxQ = 50000 + 5;
const int MaxBuckets = 250 + 5;
const int MaxNumber = MaxN + 2 * MaxQ + 5;

typedef struct Query
{
    int Command, L, R, A, B, I, J;

    Query ( ) { }

    Query ( int __Command, int __L, int __R, int __A, int __B, int __I, int __J ) : Command ( __Command ), L ( __L ), R ( __R ), A ( __A ), B ( __B ), I ( __I ), J ( __J ) { }
};

int N, Q, CntNumbers, X[MaxN], Numbers[MaxNumber], BIT[MaxBuckets][MaxNumber];
Query Queries[MaxQ];

inline void Add ( int Bucket, int idx )
{
    for ( int __idx = idx; __idx < MaxNumber; __idx += __idx & -__idx ) BIT[Bucket][__idx]++;
}

inline void Remove ( int Bucket, int idx )
{
    for ( int __idx = idx; __idx < MaxNumber; __idx += __idx & -__idx ) BIT[Bucket][__idx]--;
}

inline int Get ( int Bucket, int idx )
{
    int Ret = 0;

    for ( int __idx = idx; __idx > 0; __idx -= __idx & -__idx ) Ret += BIT[Bucket][__idx];

    return Ret;
}

map < int, int > Pos;

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

    scanf ( "%d", &N );

    int BucketSize = sqrt ( N ), BucketCount = N / BucketSize;

    if ( BucketSize * BucketSize != N ) BucketCount++;

    /*

    printf ( "velicina %d broj bucketa %d\n", BucketSize, BucketCount );

    printf ( "...\n" );
    printf ( "bucketi \n" );

    for ( int i = 0; i < BucketCount; i++ )
    {
        for ( int j = 0; j < BucketSize; j++ ) if ( i * BucketSize + j + 1 <= N ) printf ( "%d ", i * BucketSize + j + 1 );

        printf ( "\n" );
    }

    */

    for ( int i = 0; i < N; i++ )
    {
        scanf ( "%d", &X[i] );

        Numbers[CntNumbers++] = X[i];

        //printf ( "u bucket %d ubaci %d\n", i / BucketSize, X[i] );
    }

    scanf ( "%d", &Q );

    for ( int CurrQuery = 0; CurrQuery < Q; CurrQuery++ )
    {
        int Command;

        scanf ( "%d", &Command );

        if ( Command % 2 )
        {
            int L, R, A, B;

            scanf ( "%d %d %d %d", &L, &R, &A, &B );

            L--;
            R--;

            Numbers[CntNumbers++] = A;
            Numbers[CntNumbers++] = B;

            Queries[CurrQuery] = Query ( Command, L, R, A, B, -1, -1 );
        }
        else
        {
            int I, J;

            scanf ( "%d %d", &I, &J );

            I--;

            Numbers[CntNumbers++] = J;

            Queries[CurrQuery] = Query ( Command, -1, -1, -1, -1, I, J );
        }
    }

    sort ( Numbers, Numbers + CntNumbers );

    int CurrPos = 0;

    Pos[Numbers[0]] = ++CurrPos;

    for ( int i = 1; i < CntNumbers; i++ ) if ( Numbers[i] != Numbers[i - 1] ) Pos[Numbers[i]] = ++CurrPos;

    //for ( int i = 0; i < CntNumbers; i++ ) printf ( "broj %d ima poziciju %d\n", Numbers[i], Pos[Numbers[i]] );

    for ( int i = 0; i < N; i++ )
    {
        X[i] = Pos[X[i]];

        Add ( i / BucketSize, X[i] );
    }

    for ( int CurrQuery = 0; CurrQuery < Q; CurrQuery++ )
    {
        int Command = Queries[CurrQuery].Command;

        if ( Command % 2 )
        {
            int L = Queries[CurrQuery].L, R = Queries[CurrQuery].R, A = Queries[CurrQuery].A, B = Queries[CurrQuery].B;

            A = Pos[A];
            B = Pos[B];

            int BucketL = L / BucketSize, BucketR = R / BucketSize, Sol = 0;

            // sredi one izmedju
            // printf ( "%d %d\n", BucketL, BucketR );

            for ( int i = BucketL + 1; i <= BucketR - 1; i++ )
            {
                // printf ( "iz kofe %d vadim %d i vracam %d\n", i, B, A - 1 );

                Sol += Get ( i, B );
                Sol -= Get ( i, A - 1 );
            }

            // sredi tekuce buckete

            int idxL = L % BucketSize, idxR = R % BucketSize;

            if ( BucketL != BucketR )
            {
                for ( int i = BucketL * BucketSize + idxL; i <= BucketL * BucketSize + BucketSize - 1; i++ ) if ( ( A <= X[i] ) && ( X[i] <= B ) ) Sol++;

                for ( int i = BucketR * BucketSize; i <= BucketR * BucketSize + idxR; i++ ) if ( ( A <= X[i] ) && ( X[i] <= B ) ) Sol++;
            }
            else
            {
                for ( int i = BucketL * BucketSize + idxL; i <= BucketL * BucketSize + idxR; i++ ) if ( ( A <= X[i] ) && ( X[i] <= B ) ) Sol++;
            }

            printf ( "%d\n", Sol );
        }
        else
        {
            int I = Queries[CurrQuery].I, J = Queries[CurrQuery].J;

            J = Pos[J];

            // uradi update BIT-ova

            Remove ( I / BucketSize, X[I] );
            Add ( I / BucketSize, J );

            X[I] = J;
        }
    }

    /*

    printf ( "Brojevi...\n" );

    for ( int i = 0; i < CntNumbers; i++ ) printf ( "%d ", Numbers[i] );

    printf ( "\n" );

    */

    return 0;
}
