#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 200006
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

int ans[MAXN] , cn;

int T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
int sum( int x ) {
	assert( x );
	int ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%d\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 1000006
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

ll ans[MAXN]; int cn;

ll T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
int sum( int x ) {
	assert( x );
	int ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%lld\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 1000006
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

int ans[MAXN] , cn;

int T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
int sum( int x ) {
	assert( x );
	int ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%d\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 1000006
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

ll ans[MAXN]; int cn;

ll T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
ll sum( int x ) {
	assert( x );
	ll ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%lld\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 1000006
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

ll ans[MAXN]; int cn;

ll T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
int sum( int x ) {
	assert( x );
	int ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%d\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
#include "vector"
#include "map"
#include "set"
#include "queue"
#include "assert.h"
using namespace std;
#define MAXN 1000026
//#define int long long
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define all(x) (x).begin() , (x).end()
#define mem( a ) memset( a , 0 , sizeof a )
typedef long long ll;
int n , m;
int A[MAXN] , pre[MAXN] , lst[MAXN] , nxt[MAXN];

struct que {
	int op , x , y , c;
} Q[MAXN] , tmp[MAXN] ; int cnt; // 0 change

set<int> pos[MAXN];
inline int getpre( int x ) {
	return *( -- pos[A[x]].lower_bound( x ) );
}
inline int getnxt( int x ) {
	return *( pos[A[x]].upper_bound( x ) );
}

ll ans[MAXN]; int cn;

ll T[MAXN];
void add( int x , int c ) {
	assert( x );
	while( x <= n ) T[x] += c , x += ( x & -x );
}
ll sum( int x ) {
	assert( x );
	ll ret = 0;
	while( x > 0 ) ret += T[x] , x -= ( x & -x );
	return ret;
}

void cdq( int l , int r ) {
	if( l == r ) return;
	int m = l + r >> 1 , cc = 0;
	cdq( l , m ) , cdq( m + 1 , r );
	int L , R;
	for( L = l , R = m + 1 ; L <= m ; ++ L ) {
		while( R <= r && Q[R].x > Q[L].x ) {
			if( Q[R].op == 1 )
				ans[Q[R].c] += sum( Q[R].y );
			tmp[++ cc] = Q[R];
			++ R;
		}
		if( Q[L].op == 0 ) add( Q[L].y , Q[L].c );
		tmp[++ cc] = Q[L];
	}
	while( R <= r ) {
		if( Q[R].op == 1 )
			ans[Q[R].c] += sum( Q[R].y );
		tmp[++ cc] = Q[R];
		++ R;
	}
	rep( i , l , m ) if( Q[i].op == 0 ) add( Q[i].y , -Q[i].c );
	rep( i , l , r ) Q[i] = tmp[i - l + 1];
}

void solve() {
	cin >> n >> m;
	int pr;
	rep( i , 1 , n ) pos[i].insert( 0 ) , pos[i].insert( n + 1 );
	rep( i , 1 , n ) {
		scanf("%d",A + i);
		pos[A[i]].insert( i );
		pr = getpre( i );
		if( pr ) Q[++ cnt] = (que) { 0 , pr , i , i - pr };
	}
	int a , b , c , nx , nxx , prr;
	rep( i , 1 , m ) {
		scanf("%d%d%d",&a,&b,&c);
		if( a == 1 ) {
			pr = getpre( b ) , nx = getnxt( b );
			pos[A[b]].erase( b ) , A[b] = c , pos[A[b]].insert( b );
			prr = getpre( b ) , nxx = getnxt( b );
			if( nx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nx , b - nx };
			if( pr ) Q[++ cnt] = (que) { 0 , pr , b , pr - b };
			if( pr && nx != n + 1 ) Q[++ cnt] = (que) { 0 , pr , nx , nx - pr };
			if( nxx != n + 1 ) Q[++ cnt] = (que) { 0 , b , nxx , nxx - b };
			if( prr ) Q[++ cnt] = (que) { 0 , prr , b , b - prr };
			if( prr && nxx != n + 1 ) Q[++ cnt] = (que) { 0 , prr , nxx , prr - nxx };
		} else {
			++ cn , Q[++ cnt] = (que) { 1 , b , c , cn };
		}
	}
//	rep( i , 1 , cnt ) printf("%d %d %d %d\n",Q[i].op,Q[i].x,Q[i].y,Q[i].c);
	cdq( 1 , cnt );
	rep( i , 1 , cn ) printf("%lld\n",ans[i]);
}

signed main() {
//    int T;cin >> T;while( T-- ) solve();
    solve();
}


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define fi first
#define se second

using namespace std;

typedef long long ll;

const int N=500010;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0; int f=1;
  for(;c>'9'||c<'0';c=nc())if(c=='-') f=-1;
  for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=f;
}

vector<int> v;

struct Pt{
  int x,y,maxx,maxy,minx,miny,used,g,size;
  ll val,w;
  Pt *l,*r;
};

int PP;
inline bool cmp(const Pt *a,const Pt *b){
   if(PP) return a->x<b->x;
   else return a->y<b->y;
}

struct KDT{
	Pt pool[N];
	Pt *t=pool,*root;

  void dfs(Pt *cur){
    if(!cur) return ;
    if(!cur->used) cur->used=1;
    dfs(cur->l); dfs(cur->r);
  }

  inline void Up(Pt *x){
    if(!x->used)
      x->maxx=x->minx=x->x,x->maxy=x->miny=x->y,x->size=1,x->val=x->w;
    else
      x->maxx=x->maxy=-1<<30,x->minx=x->miny=1<<30,x->size=0,x->val=0;
    if(x->l){
    	x->val+=x->l->val;
      x->size+=x->l->size;
      x->maxx=max(x->l->maxx,x->maxx),x->minx=min(x->minx,x->l->minx);
      x->maxy=max(x->l->maxy,x->maxy),x->miny=min(x->miny,x->l->miny);
    }
    if(x->r){
    	x->val+=x->r->val;
      x->size+=x->r->size;
      x->maxx=max(x->r->maxx,x->maxx),x->minx=min(x->minx,x->r->minx);
      x->maxy=max(x->r->maxy,x->maxy),x->miny=min(x->miny,x->r->miny);
    }
  }

  void Extract(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return ;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b){
      dfs(cur); cur=0; return ;
    }
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return ;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used){
      cur->used=1;
    }
    Extract(cur->l,a,b,x,y); Extract(cur->r,a,b,x,y);
    Up(cur);
  }

  ll Query(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return 0;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b) return cur->val;
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return 0;
    ll ret=0;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used) ret=cur->w;
    return Query(cur->l,a,b,x,y)+Query(cur->r,a,b,x,y)+ret;
  }

  inline Pt *New(int x,int y,int v){
    t->x=t->minx=t->maxx=x;
    t->y=t->miny=t->maxy=y;
    t->used=0; t->size=1; t->val=t->w=v;
    return t++;
  }

  Pt **Rb;

  inline int Size(Pt *cur){
    if(!cur) return 0; return cur->size;
  }

  void Insert(Pt *&cur,Pt *x,int p=1){
    if(!cur) {
      cur=x; return ;
    }
    if(p){
      if(x->x>cur->x) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    else{
      if(x->y>cur->y) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    if(Size(cur->l)*0.6>=Size(cur->r) || Size(cur->r)*0.6>=Size(cur->l)) Rb=&cur,PP=p;
  }

  Pt *r[N];
  int tt;

  void dfs1(Pt *cur){
    if(!cur) return ;
    if(!cur->used) r[++tt]=cur;
    dfs1(cur->l); dfs1(cur->r);
  }

  Pt *Build(int L,int R){
    if(L>R) return 0;
    int mid=L+R>>1; Pt *ret;
    nth_element(r+L,r+mid,r+R+1,cmp);
    ret=r[mid]; PP^=1;
    ret->l=Build(L,mid-1);
    ret->r=Build(mid+1,R);
    Up(ret); return ret;
  }

  inline void rebuild(Pt *&cur){
    tt=0; dfs1(cur);
    for(int i=1;i<=tt;i++) r[i]->l=r[i]->r=0;
    cur=Build(1,tt);
  }

  inline void Insert(int x,int y,int v){
    Rb=0; Insert(root,New(x,y,v));
    if(Rb) rebuild(*Rb);
  }
}K[2];

int n,m,a[N],nxt[N],lst[N];
set<int> S[N];

inline void del(int p){
	set<int>::iterator it=S[a[p]].lower_bound(p);
	K[0].Extract(K[0].root,p,lst[p],p,lst[p]);
	K[1].Extract(K[1].root,p,nxt[p],p,nxt[p]);
	if(it!=S[a[p]].begin()){
		set<int>::iterator iit=it,nt=it; iit--; nt++;
		K[1].Extract(K[1].root,*iit,nxt[*iit],*iit,nxt[*iit]);
		if(nt!=S[a[p]].end()) nxt[*iit]=*nt; else nxt[*iit]=n+1;
		K[1].Insert(*iit,nxt[*iit],*iit);
	}
	set<int>::iterator iit=it; iit++;
	if(iit!=S[a[p]].end()){
		K[0].Extract(K[0].root,*iit,lst[*iit],*iit,lst[*iit]);
		if(it!=S[a[p]].begin()){
			it--; lst[*iit]=*it;
		}
		else lst[*iit]=0;
		K[0].Insert(*iit,lst[*iit],*iit);
	}
	S[a[p]].erase(p);
}

inline void add(int p){
	set<int>::iterator it=S[a[p]].insert(p).first;
	if(it!=S[a[p]].begin()){
		set<int>::iterator x=it; x--;
		K[1].Extract(K[1].root,*x,nxt[*x],*x,nxt[*x]);
		nxt[*x]=p; //Add(b1,nxt[*x],*x);
		K[1].Insert(*x,nxt[*x],*x);
		lst[p]=*x;
	}
	else lst[p]=0;
	//Add(b2,lst[p],p);
	K[0].Insert(p,lst[p],p);
	set<int>::iterator x=it; x++;
	if(x!=S[a[p]].end()){
		//Add(b2,lst[*x],-*x);
		K[0].Extract(K[0].root,*x,lst[*x],*x,lst[*x]);
		lst[*x]=p; //Add(b2,lst[*x],*x);
		K[0].Insert(*x,lst[*x],*x);
		nxt[p]=*x;
	}
	else nxt[p]=n+1;
	//Add(b1,nxt[p],p);
	K[1].Insert(p,nxt[p],p);
}

void PutAns(ll x){
	if(x>=10) PutAns(x/10); putchar(x%10+'0');
}

int main(){
  read(n); read(m);
	for(int i=1;i<=n;i++){
		read(a[i]);
		if(!S[a[i]].empty()){
			nxt[*S[a[i]].rbegin()]=i;
			lst[i]=*S[a[i]].rbegin();
		}
		S[a[i]].insert(i); nxt[i]=n+1;
	}
	for(int i=1;i<=n;i++){
		K[0].Insert(i,lst[i],i);
		K[1].Insert(i,nxt[i],i);
	}
	while(m--){
		int opt; read(opt);
		if(opt==1){
			int p,x; read(p); read(x);
			del(p); a[p]=x;
			add(p);
		}
		else{
			int l,r; read(l); read(r);
			PutAns(-K[0].Query(K[0].root,l,0,r,l-1)+K[1].Query(K[1].root,l,r+1,r,n+1)); putchar('\n');
		}
	}
  return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>

using namespace std;

typedef long long ll;

const int N=100010;

inline char nc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
	char c=nc(); x=0;
	for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

struct Pt{
	int x,y,mx[2],mn[2];
	ll val,tag;
	Pt *l,*r,*f;
}pool[N],*rt,*p[N],*t=pool,*pos[N];

int n,m,cnt,a[N],opt[N],x[N],y[N],lst[N];

inline Pt *New(int x,int y){
	t->x=x; t->y=y; t->val=t->tag=0;
	return t++;
}

int PP;

inline bool cmp(Pt *a,Pt *b){
	return PP?a->x<b->x:a->y<b->y;
}

inline void Up(Pt *x){
	x->mx[0]=x->mn[0]=x->x;
	x->mx[1]=x->mn[1]=x->y;
	for(int i=0;i<2;i++){
		if(x->l)
			x->mx[i]=max(x->mx[i],x->l->mx[i]),x->mn[i]=min(x->mn[i],x->l->mn[i]);
		if(x->r)
			x->mx[i]=max(x->mx[i],x->r->mx[i]),x->mn[i]=min(x->mn[i],x->r->mn[i]);
	}
}

Pt *build(int l,int r,int _=1){
	if(l>r) return 0;
	int mid=l+r>>1; PP=_;
	nth_element(p+l,p+mid,p+r+1,cmp);
	Pt *cur=p[mid];
	cur->l=build(l,mid-1,_^1);
	cur->r=build(mid+1,r,_^1);
	Up(cur);
	if(cur->l) cur->l->f=cur;
	if(cur->r) cur->r->f=cur;
	return cur;
}

void Modify(Pt *g,int x1,int y1,int x2,int y2,int v){
	if(!g || x1>x2 || y1>y2) return ;
	if(g->mx[0]<x1 || g->mn[0]>x2 || g->mx[1]<y1 || g->mn[1]>y2) return ;
	if(g->mx[0]<=x2 && g->mn[0]>=x1 && g->mn[1]>=y1 && g->mx[1]<=y2){
		g->tag+=v; return ;
	}
	if(g->x<=x2 && g->x>=x1 && g->y>=y1 && g->y<=y2) g->val+=v;
	Modify(g->l,x1,y1,x2,y2,v); Modify(g->r,x1,y1,x2,y2,v);
}

ll Query(Pt *g){
	ll ret=g->val;
	while(g){
		ret+=g->tag; g=g->f;
	}
	return ret;
}

set<int> S[N];
typedef set<int>::iterator itr;

inline void del(int x){
	itr p=S[a[x]].lower_bound(x),l=p,r=p; l--; r++;
	Modify(rt,1,x,*l,n,*l-x);
	if(r!=S[a[x]].end()){
		Modify(rt,1,*r,x,n,x-*r);
		Modify(rt,1,*r,*l,n,*r-*l);
	}
	S[a[x]].erase(x);
}

inline void add(int x){
	itr p=S[a[x]].insert(x).first,l=p,r=p; l--; r++;
	Modify(rt,1,x,*l,n,x-*l);
	if(r!=S[a[x]].end()){
		Modify(rt,1,*r,*l,n,*l-*r);
		Modify(rt,1,*r,x,n,*r-x);
	}
}

int main(){
	read(n); read(m);
	for(int i=1;i<=n;i++) read(a[i]),S[i].insert(0);
	for(int i=1;i<=m;i++){
		read(opt[i]); read(x[i]); read(y[i]);
		if(opt[i]==2){
			p[++cnt]=pos[i]=New(x[i],y[i]);
		}
	}
	rt=build(1,cnt);
	for(int i=1;i<=n;i++){
		lst[i]=*S[a[i]].rbegin(); S[a[i]].insert(i);
		Modify(rt,1,i,lst[i],n,i-lst[i]);
	}
	for(int i=1;i<=m;i++){
		if(opt[i]==2) printf("%lld\n",Query(pos[i]));
		else{
			if(y[i]==a[x[i]]) continue;
			del(x[i]); a[x[i]]=y[i]; add(y[i]);
		}
	}
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define fi first
#define se second

using namespace std;

typedef long long ll;

const int N=100010;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0; int f=1;
  for(;c>'9'||c<'0';c=nc())if(c=='-') f=-1;
  for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=f;
}

vector<int> v;

struct Pt{
  int x,y,maxx,maxy,minx,miny,used,g,size;
  ll val,w;
  Pt *l,*r;
};

int PP;
inline bool cmp(const Pt *a,const Pt *b){
   if(PP) return a->x<b->x;
   else return a->y<b->y;
}

struct KDT{
	Pt pool[N];
	Pt *t=pool,*root;

  void dfs(Pt *cur){
    if(!cur) return ;
    if(!cur->used) cur->used=1;
    dfs(cur->l); dfs(cur->r);
  }

  inline void Up(Pt *x){
    if(!x->used)
      x->maxx=x->minx=x->x,x->maxy=x->miny=x->y,x->size=1,x->val=x->w;
    else
      x->maxx=x->maxy=-1<<30,x->minx=x->miny=1<<30,x->size=0,x->val=0;
    if(x->l){
    	x->val+=x->l->val;
      x->size+=x->l->size;
      x->maxx=max(x->l->maxx,x->maxx),x->minx=min(x->minx,x->l->minx);
      x->maxy=max(x->l->maxy,x->maxy),x->miny=min(x->miny,x->l->miny);
    }
    if(x->r){
    	x->val+=x->r->val;
      x->size+=x->r->size;
      x->maxx=max(x->r->maxx,x->maxx),x->minx=min(x->minx,x->r->minx);
      x->maxy=max(x->r->maxy,x->maxy),x->miny=min(x->miny,x->r->miny);
    }
  }

  void Extract(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return ;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b){
      dfs(cur); cur=0; return ;
    }
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return ;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used){
      cur->used=1;
    }
    Extract(cur->l,a,b,x,y); Extract(cur->r,a,b,x,y);
    Up(cur);
  }

  ll Query(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return 0;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b) return cur->val;
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return 0;
    ll ret=0;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used) ret=cur->w;
    return Query(cur->l,a,b,x,y)+Query(cur->r,a,b,x,y)+ret;
  }

  inline Pt *New(int x,int y,int v){
    t->x=t->minx=t->maxx=x;
    t->y=t->miny=t->maxy=y;
    t->used=0; t->size=1; t->val=t->w=v;
    return t++;
  }

  Pt **Rb;

  inline int Size(Pt *cur){
    if(!cur) return 0; return cur->size;
  }

  void Insert(Pt *&cur,Pt *x,int p=1){
    if(!cur) {
      cur=x; return ;
    }
    if(p){
      if(x->x>cur->x) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    else{
      if(x->y>cur->y) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    if(Size(cur->l)*0.7>=Size(cur->r) || Size(cur->r)*0.7>=Size(cur->l)) Rb=&cur,PP=p;
  }

  Pt *r[N];
  int tt;

  void dfs1(Pt *cur){
    if(!cur) return ;
    if(!cur->used) r[++tt]=cur;
    dfs1(cur->l); dfs1(cur->r);
  }

  Pt *Build(int L,int R){
    if(L>R) return 0;
    int mid=L+R>>1; Pt *ret;
    nth_element(r+L,r+mid,r+R+1,cmp);
    ret=r[mid]; PP^=1;
    ret->l=Build(L,mid-1);
    ret->r=Build(mid+1,R);
    Up(ret); return ret;
  }

  inline void rebuild(Pt *&cur){
    tt=0; dfs1(cur);
    for(int i=1;i<=tt;i++) r[i]->l=r[i]->r=0;
    cur=Build(1,tt);
  }

  inline void Insert(int x,int y,int v){
    Rb=0; Insert(root,New(x,y,v));
    if(Rb) rebuild(*Rb);
  }
}K[2];

int n,m,a[N],nxt[N],lst[N];
set<int> S[N];

inline void del(int p){
	set<int>::iterator it=S[a[p]].lower_bound(p);
	K[0].Extract(K[0].root,p,lst[p],p,lst[p]);
	K[1].Extract(K[1].root,p,nxt[p],p,nxt[p]);
	if(it!=S[a[p]].begin()){
		set<int>::iterator iit=it,nt=it; iit--; nt++;
		K[1].Extract(K[1].root,*iit,nxt[*iit],*iit,nxt[*iit]);
		if(nt!=S[a[p]].end()) nxt[*iit]=*nt; else nxt[*iit]=n+1;
		K[1].Insert(*iit,nxt[*iit],*iit);
	}
	set<int>::iterator iit=it; iit++;
	if(iit!=S[a[p]].end()){
		K[0].Extract(K[0].root,*iit,lst[*iit],*iit,lst[*iit]);
		if(it!=S[a[p]].begin()){
			it--; lst[*iit]=*it;
		}
		else lst[*iit]=0;
		K[0].Insert(*iit,lst[*iit],*iit);
	}
	S[a[p]].erase(p);
}

inline void add(int p){
	set<int>::iterator it=S[a[p]].insert(p).first;
	if(it!=S[a[p]].begin()){
		set<int>::iterator x=it; x--;
		K[1].Extract(K[1].root,*x,nxt[*x],*x,nxt[*x]);
		nxt[*x]=p; //Add(b1,nxt[*x],*x);
		K[1].Insert(*x,nxt[*x],*x);
		lst[p]=*x;
	}
	else lst[p]=0;
	//Add(b2,lst[p],p);
	K[0].Insert(p,lst[p],p);
	set<int>::iterator x=it; x++;
	if(x!=S[a[p]].end()){
		//Add(b2,lst[*x],-*x);
		K[0].Extract(K[0].root,*x,lst[*x],*x,lst[*x]);
		lst[*x]=p; //Add(b2,lst[*x],*x);
		K[0].Insert(*x,lst[*x],*x);
		nxt[p]=*x;
	}
	else nxt[p]=n+1;
	//Add(b1,nxt[p],p);
	K[1].Insert(p,nxt[p],p);
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(!S[a[i]].empty()){
			nxt[*S[a[i]].rbegin()]=i;
			lst[i]=*S[a[i]].rbegin();
		}
		S[a[i]].insert(i); nxt[i]=n+1;
	}
	for(int i=1;i<=n;i++){
		K[0].Insert(i,lst[i],i);
		K[1].Insert(i,nxt[i],i);
	}
	while(m--){
		int opt; scanf("%d",&opt);
		if(opt==1){
			int p,x; scanf("%d%d",&p,&x);
			del(p); a[p]=x;
			add(p);
		}
		else{
			int l,r; scanf("%d%d",&l,&r);
			printf("%lld\n",-K[0].Query(K[0].root,l,0,r,l-1)+K[1].Query(K[1].root,l,r+1,r,n+1));
		}
	}
  return 0;
}


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define fi first
#define se second

using namespace std;

typedef long long ll;

const int N=300010;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0; int f=1;
  for(;c>'9'||c<'0';c=nc())if(c=='-') f=-1;
  for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=f;
}

vector<int> v;

struct Pt{
  int x,y,maxx,maxy,minx,miny,used,g,size;
  ll val,w;
  Pt *l,*r;
};

int PP;
inline bool cmp(const Pt *a,const Pt *b){
   if(PP) return a->x<b->x;
   else return a->y<b->y;
}

struct KDT{
	Pt pool[N];
	Pt *t=pool,*root;

  void dfs(Pt *cur){
    if(!cur) return ;
    if(!cur->used) cur->used=1;
    dfs(cur->l); dfs(cur->r);
  }

  inline void Up(Pt *x){
    if(!x->used)
      x->maxx=x->minx=x->x,x->maxy=x->miny=x->y,x->size=1,x->val=x->w;
    else
      x->maxx=x->maxy=-1<<30,x->minx=x->miny=1<<30,x->size=0,x->val=0;
    if(x->l){
    	x->val+=x->l->val;
      x->size+=x->l->size;
      x->maxx=max(x->l->maxx,x->maxx),x->minx=min(x->minx,x->l->minx);
      x->maxy=max(x->l->maxy,x->maxy),x->miny=min(x->miny,x->l->miny);
    }
    if(x->r){
    	x->val+=x->r->val;
      x->size+=x->r->size;
      x->maxx=max(x->r->maxx,x->maxx),x->minx=min(x->minx,x->r->minx);
      x->maxy=max(x->r->maxy,x->maxy),x->miny=min(x->miny,x->r->miny);
    }
  }

  void Extract(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return ;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b){
      dfs(cur); cur=0; return ;
    }
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return ;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used){
      cur->used=1;
    }
    Extract(cur->l,a,b,x,y); Extract(cur->r,a,b,x,y);
    Up(cur);
  }

  ll Query(Pt *&cur,int a,int b,int x,int y){
    if(!cur) return 0;
    if(cur->maxx<=x && cur->maxy<=y && cur->minx>=a && cur->miny>=b) return cur->val;
    if(cur->maxx<a || cur->maxy<b || cur->minx>x || cur->miny>y) return 0;
    ll ret=0;
    if(cur->x>=a && cur->x<=x && cur->y>=b && cur->y<=y && !cur->used) ret=cur->w;
    return Query(cur->l,a,b,x,y)+Query(cur->r,a,b,x,y)+ret;
  }

  inline Pt *New(int x,int y,int v){
    t->x=t->minx=t->maxx=x;
    t->y=t->miny=t->maxy=y;
    t->used=0; t->size=1; t->val=t->w=v;
    return t++;
  }

  Pt **Rb;

  inline int Size(Pt *cur){
    if(!cur) return 0; return cur->size;
  }

  void Insert(Pt *&cur,Pt *x,int p=1){
    if(!cur) {
      cur=x; return ;
    }
    if(p){
      if(x->x>cur->x) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    else{
      if(x->y>cur->y) Insert(cur->r,x,p^1); else Insert(cur->l,x,p^1);
      Up(cur);
    }
    if(Size(cur->l)*0.6>=Size(cur->r) || Size(cur->r)*0.6>=Size(cur->l)) Rb=&cur,PP=p;
  }

  Pt *r[N];
  int tt;

  void dfs1(Pt *cur){
    if(!cur) return ;
    if(!cur->used) r[++tt]=cur;
    dfs1(cur->l); dfs1(cur->r);
  }

  Pt *Build(int L,int R){
    if(L>R) return 0;
    int mid=L+R>>1; Pt *ret;
    nth_element(r+L,r+mid,r+R+1,cmp);
    ret=r[mid]; PP^=1;
    ret->l=Build(L,mid-1);
    ret->r=Build(mid+1,R);
    Up(ret); return ret;
  }

  inline void rebuild(Pt *&cur){
    tt=0; dfs1(cur);
    for(int i=1;i<=tt;i++) r[i]->l=r[i]->r=0;
    cur=Build(1,tt);
  }

  inline void Insert(int x,int y,int v){
    Rb=0; Insert(root,New(x,y,v));
    if(Rb) rebuild(*Rb);
  }
}K[2];

int n,m,a[N],nxt[N],lst[N];
set<int> S[N];

inline void del(int p){
	set<int>::iterator it=S[a[p]].lower_bound(p);
	K[0].Extract(K[0].root,p,lst[p],p,lst[p]);
	K[1].Extract(K[1].root,p,nxt[p],p,nxt[p]);
	if(it!=S[a[p]].begin()){
		set<int>::iterator iit=it,nt=it; iit--; nt++;
		K[1].Extract(K[1].root,*iit,nxt[*iit],*iit,nxt[*iit]);
		if(nt!=S[a[p]].end()) nxt[*iit]=*nt; else nxt[*iit]=n+1;
		K[1].Insert(*iit,nxt[*iit],*iit);
	}
	set<int>::iterator iit=it; iit++;
	if(iit!=S[a[p]].end()){
		K[0].Extract(K[0].root,*iit,lst[*iit],*iit,lst[*iit]);
		if(it!=S[a[p]].begin()){
			it--; lst[*iit]=*it;
		}
		else lst[*iit]=0;
		K[0].Insert(*iit,lst[*iit],*iit);
	}
	S[a[p]].erase(p);
}

inline void add(int p){
	set<int>::iterator it=S[a[p]].insert(p).first;
	if(it!=S[a[p]].begin()){
		set<int>::iterator x=it; x--;
		K[1].Extract(K[1].root,*x,nxt[*x],*x,nxt[*x]);
		nxt[*x]=p; //Add(b1,nxt[*x],*x);
		K[1].Insert(*x,nxt[*x],*x);
		lst[p]=*x;
	}
	else lst[p]=0;
	//Add(b2,lst[p],p);
	K[0].Insert(p,lst[p],p);
	set<int>::iterator x=it; x++;
	if(x!=S[a[p]].end()){
		//Add(b2,lst[*x],-*x);
		K[0].Extract(K[0].root,*x,lst[*x],*x,lst[*x]);
		lst[*x]=p; //Add(b2,lst[*x],*x);
		K[0].Insert(*x,lst[*x],*x);
		nxt[p]=*x;
	}
	else nxt[p]=n+1;
	//Add(b1,nxt[p],p);
	K[1].Insert(p,nxt[p],p);
}

void PutAns(ll x){
	if(x>=10) PutAns(x/10); putchar(x%10+'0');
}

int main(){
  read(n); read(m);
	for(int i=1;i<=n;i++){
		read(a[i]);
		if(!S[a[i]].empty()){
			nxt[*S[a[i]].rbegin()]=i;
			lst[i]=*S[a[i]].rbegin();
		}
		S[a[i]].insert(i); nxt[i]=n+1;
	}
	for(int i=1;i<=n;i++){
		K[0].Insert(i,lst[i],i);
		K[1].Insert(i,nxt[i],i);
	}
	while(m--){
		int opt; read(opt);
		if(opt==1){
			int p,x; read(p); read(x);
			del(p); a[p]=x;
			add(p);
		}
		else{
			int l,r; read(l); read(r);
			PutAns(-K[0].Query(K[0].root,l,0,r,l-1)+K[1].Query(K[1].root,l,r+1,r,n+1)); putchar('\n');
		}
	}
  return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>

using namespace std;

typedef long long ll;

const int N=100010;

inline char nc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
	char c=nc(); x=0;
	for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

struct Pt{
	int x,y,mx[2],mn[2];
	ll val,tag;
	Pt *l,*r,*f;
}pool[N],*rt,*p[N],*t=pool,*pos[N];

int n,m,cnt,a[N],opt[N],x[N],y[N],lst[N];

inline Pt *New(int x,int y){
	t->x=x; t->y=y; t->val=t->tag=0;
	return t++;
}

int PP;

inline bool cmp(Pt *a,Pt *b){
	return PP?a->x<b->x:a->y<b->y;
}

inline void Up(Pt *x){
	x->mx[0]=x->mn[0]=x->x;
	x->mx[1]=x->mn[1]=x->y;
	for(int i=0;i<2;i++){
		if(x->l)
			x->mx[i]=max(x->mx[i],x->l->mx[i]),x->mn[i]=min(x->mn[i],x->l->mn[i]);
		if(x->r)
			x->mx[i]=max(x->mx[i],x->r->mx[i]),x->mn[i]=min(x->mn[i],x->r->mn[i]);
	}
}

Pt *build(int l,int r,int _=1){
	if(l>r) return 0;
	int mid=l+r>>1; PP=_;
	nth_element(p+l,p+mid,p+r+1,cmp);
	Pt *cur=p[mid];
	cur->l=build(l,mid-1,_^1);
	cur->r=build(mid+1,r,_^1);
	Up(cur);
	if(cur->l) cur->l->f=cur;
	if(cur->r) cur->r->f=cur;
	return cur;
}

void Modify(Pt *g,int x1,int y1,int x2,int y2,int v){
	if(!g || x1>x2 || y1>y2) return ;
	if(g->mx[0]<x1 || g->mn[0]>x2 || g->mx[1]<y1 || g->mn[1]>y2) return ;
	if(g->mx[0]<=x2 && g->mn[0]>=x1 && g->mn[1]>=y1 && g->mx[1]<=y2){
		g->tag+=v; return ;
	}
	if(g->x<=x2 && g->x>=x1 && g->y>=y1 && g->y<=y2) g->val+=v;
	Modify(g->l,x1,y1,x2,y2,v); Modify(g->r,x1,y1,x2,y2,v);
}

ll Query(Pt *g){
	ll ret=g->val;
	while(g){
		ret+=g->tag; g=g->f;
	}
	return ret;
}

set<int> S[N];
typedef set<int>::iterator itr;

inline void del(int x){
	itr p=S[a[x]].lower_bound(x),l=p,r=p; l--; r++;
	Modify(rt,1,x,*l,n,*l-x);
	if(r!=S[a[x]].end()){
		Modify(rt,1,*r,x,n,x-*r);
		Modify(rt,1,*r,*l,n,*r-*l);
	}
	S[a[x]].erase(x);
}

inline void add(int x){
	itr p=S[a[x]].insert(x).first,l=p,r=p; l--; r++;
	Modify(rt,1,x,*l,n,x-*l);
	if(r!=S[a[x]].end()){
		Modify(rt,1,*r,*l,n,*l-*r);
		Modify(rt,1,*r,x,n,*r-x);
	}
}

int main(){
	read(n); read(m);
	for(int i=1;i<=n;i++) read(a[i]),S[i].insert(0);
	for(int i=1;i<=m;i++){
		read(opt[i]); read(x[i]); read(y[i]);
		if(opt[i]==2){
			p[++cnt]=pos[i]=New(x[i],y[i]);
		}
	}
	rt=build(1,cnt);
	for(int i=1;i<=n;i++){
		lst[i]=*S[a[i]].rbegin(); S[a[i]].insert(i);
		Modify(rt,1,i,lst[i],n,i-lst[i]);
	}
	for(int i=1;i<=m;i++){
		if(opt[i]==2) printf("%lld\n",Query(pos[i]));
		else{
			if(y[i]==a[x[i]]) continue;
			del(x[i]); a[x[i]]=y[i]; add(x[i]);
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005;
set<int> s[N];
int a[N],tmpa[N];
struct queries
{
  int x,y,z;
}arr[N];
struct innerbit
{
  vi vals;
  vector<ll> bit;
  void insert(int y)
  {
    vals.PB(y);
  }
  void updateinner(int y,int val)
  {
    int i=upper_bound(vals.begin(),vals.end(),y)-vals.begin()-1;
    while(i>0)
      {
	bit[i]+=val;
	i-=(i&(-i));
      }
  }
  ll queryinner(int y)
  {
    int i=lower_bound(vals.begin(),vals.end(),y)-vals.begin();
    if(i==vals.size()) return 0;
    ll ans=0;
    while(i<bit.size())
      {
	ans+=bit[i];
	i+=(i&(-i));
      }
    return ans;
  }
  void init()
  {
    vals.PB(0);
    sort(vals.begin(),vals.end());
    vals.erase(unique(vals.begin(),vals.end()),vals.end());
    bit.assign((int)vals.size()+3,0);
  }
}bit[N];
void update(int type,int x,int y,int val)
{
  int tmp=x;
  while(x<N)
    {
      if(type)
	bit[x].updateinner(y,val);
      else
	bit[x].insert(y);
      x+=(x&(-x));
    }
}
ll query(int l,int r)
{
  ll ans=0;
  while(r>0)
    {
      ans+=bit[r].queryinner(l);
      r-=(r&(-r));
    }
  return ans;
}
void eraseelem(int type,int l)
{
  auto it=s[a[l]].find(l),it1=it;
  if(it!=s[a[l]].begin())
    update(type,l,*prev(it),-l+*prev(it));
  it1++;
  if(it1!=s[a[l]].end())
    {
      update(type,*it1,l,l-*it1);
      if(it!=s[a[l]].begin())
	update(type,*it1,*prev(it),*it1-*prev(it));
    }
  s[a[l]].erase(l);
}
void insertelem(int type,int l)
{
  s[a[l]].insert(l);
  auto it=s[a[l]].find(l),it1=it;
  it1++;
  if(it1!=s[a[l]].end())
    {
      if(it!=s[a[l]].begin())
	update(type,*it1,*prev(it),*prev(it)-*it1);
      update(type,*it1,l,*it1-l);
    }
  if(it!=s[a[l]].begin())
    update(type,l,*prev(it),l-*prev(it));
}
int main()
{
  int n,q,i,j;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]); tmpa[i]=a[i];
    }
  rep(i,1,q+1)
    {
      si(arr[i].x); si(arr[i].y); si(arr[i].z);
    }
  rep(j,0,2)
    {
      rep(i,0,N)
	{
	  bit[i].init();
	  s[i].clear();
	}
      rep(i,1,n+1) a[i]=tmpa[i];
      rep(i,1,n+1)
	s[a[i]].insert(i);
      int prev1=0;
      rep(i,1,N)
	{
	  if(s[i].size()==0) continue;
	  prev1=*s[i].begin();
	  for(auto it2:s[i])
	    {
	      update(j,it2,prev1,it2-prev1);
	      prev1=it2;
	    }
	}
      rep(i,1,q+1)
	{
	  if(arr[i].x==1)
	    {
	      eraseelem(j,arr[i].y);
	      a[arr[i].y]=arr[i].z;
	      insertelem(j,arr[i].y);
	    }
	  else if(j)
	    lldout(query(arr[i].y,arr[i].z));
	}
    }
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005,LOGN=20;
map<int,set<int> > s;
int a[N];
int root[N],le[N*LOGN],re[N*LOGN];
ll seg[N*LOGN];
int cnt=0;
int updateinner(int low,int high,int ind,int y,int val)
{
  int tmp=++cnt;
  seg[tmp]=seg[ind]+val;
  if(low==high)
    return tmp;
  int mid=(low+high)>>1;
  if(y<=mid)
    {
      le[tmp]=updateinner(low,mid,le[ind],y,val);
      re[tmp]=re[ind];
    }
  else
    {
      le[tmp]=le[ind];
      re[tmp]=updateinner(mid+1,high,re[ind],y,val);
    }
  return tmp;
}
ll queryinner(int low,int high,int ind,int l,int r)
{
  if(high<l || low>r) return 0;
  if(low>=l && high<=r)
    return seg[ind];
  int mid=(low+high)>>1;
  return queryinner(low,mid,le[ind],l,r)+queryinner(mid+1,high,re[ind],l,r);
}
void update(int x,int y,int val)
{
  while(x<N)
    {
      root[x]=updateinner(1,N,root[x],y,val);
      x+=(x&(-x));
    }
}
ll query(int l,int r)
{
  ll ans=0;
  while(r>0)
    {
      ans+=queryinner(1,N,root[r],l,r);
      r-=(r&(-r));
    }
  return ans;
}
/*void update(int low,int high,int pos,int x,int y,int val)
{
  if(low==high)
    {
      root[pos]=updateinner(1,N,root[pos],y,val);
      return;
    }
  int mid=(low+high)>>1;
  if(x<=mid)
    update(low,mid,2*pos,x,y,val);
  else
    update(mid+1,high,2*pos+1,x,y,val);
  root[pos]=updateinner(1,N,root[pos],y,val);
}
ll query(int low,int high,int pos,int l,int r)
{
  if(low>r || high<l)
    return 0;
  if(low>=l && high<=r)
    {
      //trace2(low,high);
      return queryinner(1,N,root[pos],l,r);
    }
  int mid=(low+high)>>1;
  return query(low,mid,2*pos,l,r)+query(mid+1,high,2*pos+1,l,r);
}*/
int main()
{
  int n,q,i,l,r;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]);
      s[a[i]].insert(i);
    }
  int prev1=0;
  for(auto it1:s)
    {
      prev1=*it1.se.begin();
      for(auto it2:it1.se)
	{
	  //trace3(it2,prev1,it2-prev1);
	  update(it2,prev1,it2-prev1);
	  prev1=it2;
	}
    }
  int ch;
  while(q--)
    {
      si(ch); si(l); si(r);
      if(ch==2)
	lldout(query(l,r));
      else
	{
	  //removing
	  auto it=s[a[l]].find(l),it1=it;
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),-l+*prev(it));
	  it1++;
	  if(it1!=s[a[l]].end())
	    {
	      update(*it1,l,l-*it1);
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*it1-*prev(it));
	    }
	  s[a[l]].erase(l);
	  //inserting
	  a[l]=r;
	  s[a[l]].insert(l);
	  it=s[a[l]].find(l);
	  it1=it; it1++;
	  if(it1!=s[a[l]].end())
	    {
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*prev(it)-*it1);
	      update(*it1,l,*it1-l);
	    }
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),l-*prev(it));
	}
    }
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005,LOGN=20;
map<int,set<int> > s;
int a[N];
int root[2*N],le[4*N*LOGN],re[4*N*LOGN];
ll seg[N*LOGN*LOGN];
int cnt=0;
int updateinner(int low,int high,int ind,int y,int val)
{
  int tmp=++cnt;
  seg[tmp]=seg[ind]+val;
  if(low==high)
    return tmp;
  int mid=(low+high)>>1;
  if(y<=mid)
    {
      le[tmp]=updateinner(low,mid,le[ind],y,val);
      re[tmp]=re[ind];
    }
  else
    {
      le[tmp]=le[ind];
      re[tmp]=updateinner(mid+1,high,re[ind],y,val);
    }
  return tmp;
}
ll queryinner(int low,int high,int ind,int l,int r)
{
  if(high<l || low>r) return 0;
  if(low>=l && high<=r)
    return seg[ind];
  int mid=(low+high)>>1;
  return queryinner(low,mid,le[ind],l,r)+queryinner(mid+1,high,re[ind],l,r);
}
void update(int x,int y,int val)
{
  while(x<N)
    {
      root[x]=updateinner(1,N,root[x],y,val);
      x+=(x&(-x));
    }
}
ll query(int l,int r)
{
  ll ans=0;
  while(r>0)
    {
      ans+=queryinner(1,N,root[r],l,r);
      r-=(r&(-r));
    }
  return ans;
}
/*void update(int low,int high,int pos,int x,int y,int val)
{
  if(low==high)
    {
      root[pos]=updateinner(1,N,root[pos],y,val);
      return;
    }
  int mid=(low+high)>>1;
  if(x<=mid)
    update(low,mid,2*pos,x,y,val);
  else
    update(mid+1,high,2*pos+1,x,y,val);
  root[pos]=updateinner(1,N,root[pos],y,val);
}
ll query(int low,int high,int pos,int l,int r)
{
  if(low>r || high<l)
    return 0;
  if(low>=l && high<=r)
    {
      //trace2(low,high);
      return queryinner(1,N,root[pos],l,r);
    }
  int mid=(low+high)>>1;
  return query(low,mid,2*pos,l,r)+query(mid+1,high,2*pos+1,l,r);
}*/
int main()
{
  int n,q,i,l,r;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]);
      s[a[i]].insert(i);
    }
  int prev1=0;
  for(auto it1:s)
    {
      prev1=*it1.se.begin();
      for(auto it2:it1.se)
	{
	  //trace3(it2,prev1,it2-prev1);
	  update(it2,prev1,it2-prev1);
	  prev1=it2;
	}
    }
  int ch;
  while(q--)
    {
      si(ch); si(l); si(r);
      if(ch==2)
	lldout(query(l,r));
      else
	{
	  //removing
	  auto it=s[a[l]].find(l),it1=it;
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),-l+*prev(it));
	  it1++;
	  if(it1!=s[a[l]].end())
	    {
	      update(*it1,l,l-*it1);
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*it1-*prev(it));
	    }
	  s[a[l]].erase(l);
	  //inserting
	  a[l]=r;
	  s[a[l]].insert(l);
	  it=s[a[l]].find(l);
	  it1=it; it1++;
	  if(it1!=s[a[l]].end())
	    {
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*prev(it)-*it1);
	      update(*it1,l,*it1-l);
	    }
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),l-*prev(it));
	}
    }
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005,LOGN=17;
map<int,set<int> > s;
int a[N];
int seg[N*LOGN*LOGN],root[4*N],le[N*LOGN],re[N*LOGN];
int cnt=0;
int updateinner(int low,int high,int ind,int y,int val)
{
  int tmp=++cnt;
  seg[tmp]=seg[ind]+val;
  if(low==high)
    return tmp;
  int mid=(low+high)>>1;
  if(y<=mid)
    {
      le[tmp]=updateinner(low,mid,le[ind],y,val);
      re[tmp]=re[ind];
    }
  else
    {
      le[tmp]=le[ind];
      re[tmp]=updateinner(mid+1,high,re[ind],y,val);
    }
  return tmp;
}
ll queryinner(int low,int high,int ind,int l,int r)
{
  //trace3(seg[ind],l,r);
  if(high<l || low>r) return 0;
  if(low>=l && high<=r)
    return seg[ind];
  int mid=(low+high)>>1;
  return queryinner(low,mid,le[ind],l,r)+queryinner(mid+1,high,re[ind],l,r);
}
void update(int low,int high,int pos,int x,int y,int val)
{
  if(low==high)
    {
      root[pos]=updateinner(1,N,root[pos],y,val);
      return;
    }
  int mid=(low+high)>>1;
  if(x<=mid)
    update(low,mid,2*pos,x,y,val);
  else
    update(mid+1,high,2*pos+1,x,y,val);
  root[pos]=updateinner(1,N,root[pos],y,val);
}
ll query(int low,int high,int pos,int l,int r)
{
  if(low>r || high<l)
    return 0;
  if(low>=l && high<=r)
    {
      //trace2(low,high);
      return queryinner(1,N,root[pos],l,r);
    }
  int mid=(low+high)>>1;
  return query(low,mid,2*pos,l,r)+query(mid+1,high,2*pos+1,l,r);
}
int main()
{
  int n,q,i,l,r;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]);
      s[a[i]].insert(i);
    }
  int prev1=0;
  for(auto it1:s)
    {
      prev1=*it1.se.begin();
      for(auto it2:it1.se)
	{
	  //trace3(it2,prev1,it2-prev1);
	  update(1,n,1,it2,prev1,it2-prev1);
	  prev1=it2;
	}
    }
  int ch;
  while(q--)
    {
      si(ch); si(l); si(r);
      if(ch==2)
	lldout(query(1,n,1,l,r));
      else
	{
	  //removing
	  auto it=s[a[l]].find(l),it1=it;
	  if(it!=s[a[l]].begin())
	    update(1,n,1,l,*prev(it),-l+*prev(it));
	  it1++;
	  if(it1!=s[a[l]].end())
	    {
	      update(1,n,1,*it1,l,l-*it1);
	      if(it!=s[a[l]].begin())
		update(1,n,1,*it1,*prev(it),*it1-*prev(it));
	    }
	  s[a[l]].erase(l);
	  //inserting
	  a[l]=r;
	  s[a[l]].insert(l);
	  it=s[a[l]].find(l);
	  it1=it; it1++;
	  if(it1!=s[a[l]].end())
	    {
	      if(it!=s[a[l]].begin())
		update(1,n,1,*it1,*prev(it),*prev(it)-*it1);
	      update(1,n,1,*it1,l,*it1-l);
	    }
	  if(it!=s[a[l]].begin())
	    update(1,n,1,l,*prev(it),l-*prev(it));
	}
    }
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005,LOGN=20;
map<int,set<int> > s;
int a[N];
int root[2*N],le[10*N*LOGN],re[10*N*LOGN];
int seg[10*N*LOGN];
int cnt=0;
int updateinner(int low,int high,int ind,int y,int val)
{
  int tmp=++cnt;
  seg[tmp]=seg[ind]+val;
  if(low==high)
    return tmp;
  int mid=(low+high)>>1;
  if(y<=mid)
    {
      le[tmp]=updateinner(low,mid,le[ind],y,val);
      re[tmp]=re[ind];
    }
  else
    {
      le[tmp]=le[ind];
      re[tmp]=updateinner(mid+1,high,re[ind],y,val);
    }
  return tmp;
}
ll queryinner(int low,int high,int ind,int l,int r)
{
  if(high<l || low>r) return 0;
  if(low>=l && high<=r)
    return seg[ind];
  int mid=(low+high)>>1;
  return queryinner(low,mid,le[ind],l,r)+queryinner(mid+1,high,re[ind],l,r);
}
void update(int x,int y,int val)
{
  while(x<N)
    {
      root[x]=updateinner(1,N,root[x],y,val);
      x+=(x&(-x));
    }
}
ll query(int l,int r)
{
  ll ans=0;
  while(r>0)
    {
      ans+=queryinner(1,N,root[r],l,r);
      r-=(r&(-r));
    }
  return ans;
}
/*void update(int low,int high,int pos,int x,int y,int val)
{
  if(low==high)
    {
      root[pos]=updateinner(1,N,root[pos],y,val);
      return;
    }
  int mid=(low+high)>>1;
  if(x<=mid)
    update(low,mid,2*pos,x,y,val);
  else
    update(mid+1,high,2*pos+1,x,y,val);
  root[pos]=updateinner(1,N,root[pos],y,val);
}
ll query(int low,int high,int pos,int l,int r)
{
  if(low>r || high<l)
    return 0;
  if(low>=l && high<=r)
    {
      //trace2(low,high);
      return queryinner(1,N,root[pos],l,r);
    }
  int mid=(low+high)>>1;
  return query(low,mid,2*pos,l,r)+query(mid+1,high,2*pos+1,l,r);
}*/
int main()
{
  int n,q,i,l,r;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]);
      s[a[i]].insert(i);
    }
  int prev1=0;
  for(auto it1:s)
    {
      prev1=*it1.se.begin();
      for(auto it2:it1.se)
	{
	  //trace3(it2,prev1,it2-prev1);
	  update(it2,prev1,it2-prev1);
	  prev1=it2;
	}
    }
  int ch;
  while(q--)
    {
      si(ch); si(l); si(r);
      if(ch==2)
	lldout(query(l,r));
      else
	{
	  //removing
	  auto it=s[a[l]].find(l),it1=it;
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),-l+*prev(it));
	  it1++;
	  if(it1!=s[a[l]].end())
	    {
	      update(*it1,l,l-*it1);
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*it1-*prev(it));
	    }
	  s[a[l]].erase(l);
	  //inserting
	  a[l]=r;
	  s[a[l]].insert(l);
	  it=s[a[l]].find(l);
	  it1=it; it1++;
	  if(it1!=s[a[l]].end())
	    {
	      if(it!=s[a[l]].begin())
		update(*it1,*prev(it),*prev(it)-*it1);
	      update(*it1,l,*it1-l);
	    }
	  if(it!=s[a[l]].begin())
	    update(l,*prev(it),l-*prev(it));
	}
    }
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
typedef long long int ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<pii> vpii;

#define mi 1000000007
#define rep(i,a,b) for(i=a;i<b;i++)
#define repv(i,a,b) for(i=b-1;i>=a;i--)
#define pr(arr,n) rep(i,0,n) cout<<arr[i]<<" "; cout<<endl;
#define pr1(arr,n) rep(i,1,n+1) cout<<arr[i]<<" "; cout<<endl;
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)

#define TRACE

#ifdef TRACE
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#else

#define trace1(x)
#define trace2(x, y)
#define trace3(x, y, z)
#define trace4(a, b, c, d)
#define trace5(a, b, c, d, e)
#define trace6(a, b, c, d, e, f)

#endif

int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);}
int lcm(int a,int b) { return a*(b/gcd(a,b));}

ll pow1(ll a,ll b)
{
  ll ans=1;
  while(b>0)
    {
      if(b&1) ans=(ans*a)%mi;
      a=(a*a)%mi; b>>=1;
    }
  return ans;
}
const int N=100005,LOGN=20;
map<int,set<int> > s;
int a[N];
int seg[N*LOGN*LOGN],root[4*N],le[N*LOGN*LOGN],re[N*LOGN*LOGN];
int cnt=0;
int updateinner(int low,int high,int ind,int y,int val)
{
  int tmp=++cnt;
  seg[tmp]=seg[ind]+val;
  if(low==high)
    return tmp;
  int mid=(low+high)>>1;
  if(y<=mid)
    {
      le[tmp]=updateinner(low,mid,le[ind],y,val);
      re[tmp]=re[ind];
    }
  else
    {
      le[tmp]=le[ind];
      re[tmp]=updateinner(mid+1,high,re[ind],y,val);
    }
  return tmp;
}
ll queryinner(int low,int high,int ind,int l,int r)
{
  //trace3(seg[ind],l,r);
  if(high<l || low>r) return 0;
  if(low>=l && high<=r)
    return seg[ind];
  int mid=(low+high)>>1;
  return queryinner(low,mid,le[ind],l,r)+queryinner(mid+1,high,re[ind],l,r);
}
void update(int low,int high,int pos,int x,int y,int val)
{
  if(low==high)
    {
      root[pos]=updateinner(1,N,root[pos],y,val);
      return;
    }
  int mid=(low+high)>>1;
  if(x<=mid)
    update(low,mid,2*pos,x,y,val);
  else
    update(mid+1,high,2*pos+1,x,y,val);
  root[pos]=updateinner(1,N,root[pos],y,val);
}
ll query(int low,int high,int pos,int l,int r)
{
  if(low>r || high<l)
    return 0;
  if(low>=l && high<=r)
    {
      //trace2(low,high);
      return queryinner(1,N,root[pos],l,r);
    }
  int mid=(low+high)>>1;
  return query(low,mid,2*pos,l,r)+query(mid+1,high,2*pos+1,l,r);
}
int main()
{
  int n,q,i,l,r;
  si(n); si(q);
  rep(i,1,n+1)
    {
      si(a[i]);
      s[a[i]].insert(i);
    }
  int prev1=0;
  for(auto it1:s)
    {
      prev1=*it1.se.begin();
      for(auto it2:it1.se)
	{
	  //trace3(it2,prev1,it2-prev1);
	  update(1,n,1,it2,prev1,it2-prev1);
	  prev1=it2;
	}
    }
  int ch;
  while(q--)
    {
      si(ch); si(l); si(r);
      if(ch==2)
	lldout(query(1,n,1,l,r));
      else
	{
	  //removing
	  auto it=s[a[l]].find(l),it1=it;
	  if(it!=s[a[l]].begin())
	    update(1,n,1,l,*prev(it),-l+*prev(it));
	  it1++;
	  if(it1!=s[a[l]].end())
	    {
	      update(1,n,1,*it1,l,l-*it1);
	      if(it!=s[a[l]].begin())
		update(1,n,1,*it1,*prev(it),*it1-*prev(it));
	    }
	  s[a[l]].erase(l);
	  //inserting
	  a[l]=r;
	  s[a[l]].insert(l);
	  it=s[a[l]].find(l);
	  it1=it; it1++;
	  if(it1!=s[a[l]].end())
	    {
	      if(it!=s[a[l]].begin())
		update(1,n,1,*it1,*prev(it),*prev(it)-*it1);
	      update(1,n,1,*it1,l,*it1-l);
	    }
	  if(it!=s[a[l]].begin())
	    update(1,n,1,l,*prev(it),l-*prev(it));
	}
    }
  return 0;
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;

public class xyz {

	public static void main(String[] args) {
		Scanner s=new Scanner(System.in);
		int n=s.nextInt();
		int k=s.nextInt();

		int[] arr=new int[n];
		for(int i=0;i<n;i++)
		{
			arr[i]=s.nextInt();
		}

		Arrays.sort(arr);

		int[] psa=new int[n];
		int csum=0;
		for(int i=0;i<n;i++)
		{
			csum+=arr[i];
			psa[i]=csum;
		}
		int[] dp=new int[n];
		for(int i=0;i<n;i++)
		{
			if(i<k)
			{
				dp[i]=psa[i];
				//System.out.print(psa[i]+" ");
			}
			else
			{
				int idx=i-k;
				int left=psa[idx];
				int right=psa[i]-psa[idx];
				dp[i]=dp[idx]+right+left;
				//System.out.print(2*left+right+" ");
			}
		}

		for(int val:dp)
		{
			System.out.print(val+" ");
		}

	}

}


import java.util.*;

public class SweetsGreedy {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        Integer arr[] = new Integer[n];

        for(int i=0;i<n;i++) {
            arr[i] = sc.nextInt();
        }

        Arrays.sort(arr, Collections.reverseOrder());

        long presum[] = new long[n];
        presum[0] = arr[0];

        for(int i=1;i<n;i++){
            presum[i] = presum[i-1] + arr[i];
            // System.out.print(presum[i]+" ");
        }

        long ans[] = new long[n];

        for(int i=0;i<n;i++){
            int day = 1;
            int j = i;
            while(j<n) {
                // System.out.print(j+" ");
                ans[i] += day * (presum[j+m-1 >= n ? n-1 : j+m-1] - presum[j] + arr[j]);
                day++;
                j += m;
            }
        }
        for(int i=n-1;i>=0;i--) {
            System.out.print(ans[i]+" ");
        }
    }
}


import java.io.*;
import java.util.*;

public class SweetsEating {

	public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt();int m = in.nextInt();
		Integer arr[] = new Integer[n];for(int i=0;i<n;i++) arr[i] = in.nextInt();
		Arrays.sort(arr);
		long prefixSum[] = new long[n];
		prefixSum[0] = arr[0];
		for(int i=1;i<n;i++) prefixSum[i] = prefixSum[i-1]+arr[i];
		long ans[] = new long[n];
		for(int i=0;i<n;i++) {
			ans[i] = prefixSum[i];
			if(i-m>=0)
				ans[i] += ans[i-m];
		}
		for(long i : ans)
			out.print(i+" ");
		out.close();
	}
}


import java.util.*;

public class Sweets {

    // static int res[];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        // res = new int[n];
        // Arrays.fill(res, -1);
        Integer arr[] = new Integer[n];
        for(int i=0;i<n;i++) {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr, Collections.reverseOrder());
        int dp[][] = new int[n][n+1];
        for(int d[]: dp) {
            Arrays.fill(d, -1);
        }
        helper(arr, 0, m, 1, dp);
        StringBuilder sb = new StringBuilder();
        for(int i=n-1;i>=0;i--) {
            sb.append(helper(arr, i, m, 1, dp)+" ");
            // System.out.print(res[i]+" ");
            // for(int j=1;j<=n;j++) {
            //     System.out.print(dp[i][j]+" ");
            // }
            // System.out.println();
        }
        System.out.print(sb.toString());
    }

    public static int helper(Integer arr[], int pos, int m, int day, int dp[][]) {
        if(pos==arr.length) {
            return 0;
        }
        // if(day>arr.length) {
        //     return Integer.MAX_VALUE;
        // }

        if(dp[pos][day]!=-1) {
            return dp[pos][day];
        }

        int p = Integer.MAX_VALUE/10;
        // for(int i=pos;i<arr.length;i++) {
            int sum = 0;
            for(int j=pos;j<Math.min(arr.length, pos+m);j++) {
                sum += arr[j];
                int h = helper(arr, j+1, m, day+1, dp);
                // if(res[j] == -1) res[j] = h;
                p = Math.min(p, sum*day+h);
            }

        // }
        return dp[pos][day] = p;
    }
}


import java.util.*;

public class SweetsGreedy {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        Integer arr[] = new Integer[n];

        for(int i=0;i<n;i++) {
            arr[i] = sc.nextInt();
        }

        Arrays.sort(arr, Collections.reverseOrder());

        int presum[] = new int[n];
        presum[0] = arr[0];

        for(int i=1;i<n;i++){
            presum[i] = presum[i-1] + arr[i];
            // System.out.print(presum[i]+" ");
        }

        int ans[] = new int[n];

        for(int i=0;i<n;i++){
            int day = 1;
            int j = i;
            while(j<n) {
                // System.out.print(j+" ");
                ans[i] += day * (presum[j+m-1 >= n ? n-1 : j+m-1] - presum[j] + arr[j]);
                day++;
                j += m;
            }
        }
        for(int i=n-1;i>=0;i--) {
            System.out.print(ans[i]+" ");
        }
    }
}


import java.io.*;
import java.util.*;
import java.util.logging.Logger;

public class Main {
    static BufferedReader br;

    public static void main(String[] args) throws Exception {
        br = new BufferedReader(new InputStreamReader(System.in));
        String[] arr = cinA();
        int n =  getI(arr[0]);
        int m = getI(arr[1]);
        String[] data = cinA();
        int [] a = new int[n];
        for(int i=0;i<n;i++){
            a[i]=getI(data[i]);
        }
        Arrays.sort(a);
        int[] pre  = new int[n];
        pre[0]=a[0];
        for(int j=1;j<n;j++){
            pre[j]=pre[j-1]+a[j];
        }

            int[] dp = new int[n];
            StringBuilder ob=  new StringBuilder();
            dp[0]=pre[0];
            ob.append(String.valueOf(dp[0]+" "));
            for (int j = 1; j < n; j++) {
              dp[j]=pre[j];
              if(j-m>=0){
                  dp[j]=dp[j]+dp[j-m];
              }
                ob.append(String.valueOf(dp[j]+" "));
            }
            System.out.println(ob.toString());
            System.exit(0);

    }

    public static int binary(long val,long[] arr){
        //    System.out.println("value "+ val);
        int i=0;
        int mid= 0;
        int e = arr.length;
        while(i<=e){
            //    System.out.println(i+ " "+e);

            mid = (i+e)/2;

            if(arr[mid]==val){

                return mid;
            }
            if(arr[mid]>val){

                e=mid-1;
                continue;
            }
            i=mid+1;

        }
        // System.out.println(mid);
        return mid;
    }

    public static void arrinit(String[] a,long[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Long.parseLong(a[i]);
        }
    }
    public static void arrinit(String[] a,int[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Integer.parseInt(a[i]);
        }
    }

    static double findRoots(int a, int b, int c) {
        // If a is 0, then equation is not
        //quadratic, but linear

        int d = b * b - 4 * a * c;
        double sqrt_val = Math.sqrt(Math.abs(d));

        // System.out.println("Roots are real and different \n");

        return Math.max((double) (-b + sqrt_val) / (2 * a),
                (double) (-b - sqrt_val) / (2 * a));

    }

    public static String cin() throws Exception {
        return br.readLine();
    }

    public static String[] cinA() throws Exception {
        return br.readLine().split(" ");
    }
    public static String[] cinA(int x) throws Exception{
        return br.readLine().split("");
    }

    public static String ToString(Long x) {
        return Long.toBinaryString(x);
    }

    public static void cout(String s) {
        System.out.println(s);
    }

    public static Integer cinI() throws Exception {
        return Integer.parseInt(br.readLine());
    }

    public static int getI(String s) throws Exception {
        return Integer.parseInt(s);
    }

    public static long getL(String s) throws Exception {
        return Long.parseLong(s);
    }

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

    public static void coutI(int x) {
        System.out.println(String.valueOf(x));
    }

    public static void coutI(long x) {
        System.out.println(String.valueOf(x));
    }

    public static Long cinL() throws Exception {
        return Long.parseLong(br.readLine());
    }

    public static void arrInit(String[] arr, int[] arr1) throws Exception {
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = getI(arr[i]);
        }

    }
}

class range {
    int l;
    int r;
    int diff;

    public range(int l, int r, int diff) {
        this.l = l;
        this.r = r;
        this.diff = diff;
    }
}

class sortRange implements Comparator<range> {

    @Override
    public int compare(range range, range t1) {
        if (range.diff != t1.diff)
            return t1.diff - range.diff;
        return range.l - t1.l;

    }}


import java.io.*;
import java.util.*;
import java.util.logging.Logger;

public class Main {
    static BufferedReader br;

    public static void main(String[] args) throws Exception {
        br = new BufferedReader(new InputStreamReader(System.in));
        String[] arr = cinA();
        int n =  getI(arr[0]);
        int m = getI(arr[1]);
        String[] data = cinA();
        int [] a = new int[n];
        for(int i=0;i<n;i++){
            a[i]=getI(data[i]);
        }
        Arrays.sort(a);
        int[] pre  = new int[n];
        pre[0]=a[0];
        for(int j=1;j<n;j++){
            pre[j]=pre[j-1]+a[j];
        }
        if(m!=1) {
            int[] dp = new int[n];
            StringBuilder ob=  new StringBuilder();
            dp[0]=pre[0];
            ob.append(String.valueOf(dp[0]+" "));
            for (int j = 1; j < n; j++) {
              dp[j]=pre[j];
              if(j-m>=0){
                  dp[j]=dp[j]+dp[j-m];
              }
                ob.append(String.valueOf(dp[j]+" "));
            }
            System.out.println(ob.toString());
            System.exit(0);
        }
        StringBuilder ob = new StringBuilder();
        for(int j=0;j<n;j++){
            ob.append(String.valueOf(pre[0]+" "));
        }
        System.out.println(ob.toString());
        System.exit(0);
    }

    public static int binary(long val,long[] arr){
        //    System.out.println("value "+ val);
        int i=0;
        int mid= 0;
        int e = arr.length;
        while(i<=e){
            //    System.out.println(i+ " "+e);

            mid = (i+e)/2;

            if(arr[mid]==val){

                return mid;
            }
            if(arr[mid]>val){

                e=mid-1;
                continue;
            }
            i=mid+1;

        }
        // System.out.println(mid);
        return mid;
    }

    public static void arrinit(String[] a,long[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Long.parseLong(a[i]);
        }
    }
    public static void arrinit(String[] a,int[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Integer.parseInt(a[i]);
        }
    }

    static double findRoots(int a, int b, int c) {
        // If a is 0, then equation is not
        //quadratic, but linear

        int d = b * b - 4 * a * c;
        double sqrt_val = Math.sqrt(Math.abs(d));

        // System.out.println("Roots are real and different \n");

        return Math.max((double) (-b + sqrt_val) / (2 * a),
                (double) (-b - sqrt_val) / (2 * a));

    }

    public static String cin() throws Exception {
        return br.readLine();
    }

    public static String[] cinA() throws Exception {
        return br.readLine().split(" ");
    }
    public static String[] cinA(int x) throws Exception{
        return br.readLine().split("");
    }

    public static String ToString(Long x) {
        return Long.toBinaryString(x);
    }

    public static void cout(String s) {
        System.out.println(s);
    }

    public static Integer cinI() throws Exception {
        return Integer.parseInt(br.readLine());
    }

    public static int getI(String s) throws Exception {
        return Integer.parseInt(s);
    }

    public static long getL(String s) throws Exception {
        return Long.parseLong(s);
    }

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

    public static void coutI(int x) {
        System.out.println(String.valueOf(x));
    }

    public static void coutI(long x) {
        System.out.println(String.valueOf(x));
    }

    public static Long cinL() throws Exception {
        return Long.parseLong(br.readLine());
    }

    public static void arrInit(String[] arr, int[] arr1) throws Exception {
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = getI(arr[i]);
        }

    }
}

class range {
    int l;
    int r;
    int diff;

    public range(int l, int r, int diff) {
        this.l = l;
        this.r = r;
        this.diff = diff;
    }
}

class sortRange implements Comparator<range> {

    @Override
    public int compare(range range, range t1) {
        if (range.diff != t1.diff)
            return t1.diff - range.diff;
        return range.l - t1.l;

}}


//package com.company;
import java.io.*;
import java.util.*;
import java.util.logging.Logger;

public class Main {
    static BufferedReader br;

    public static void main(String[] args) throws Exception {
        br = new BufferedReader(new InputStreamReader(System.in));
        String[] arr = cinA();
        int n =  getI(arr[0]);
        int m = getI(arr[1]);
        String[] data = cinA();
        int [] a = new int[n];
        for(int i=0;i<n;i++){
            a[i]=getI(data[i]);
        }
        Arrays.sort(a);
        long[] pre  = new long[n];
        pre[0]=a[0];
        for(int j=1;j<n;j++){
            pre[j]=pre[j-1]+a[j];
        }

        long[] dp = new long[n];
            StringBuilder ob=  new StringBuilder();
            dp[0]=pre[0];
            ob.append(String.valueOf(dp[0]+" "));
            for (int j = 1; j < n; j++) {
              dp[j]=pre[j];
              if(j-m>=0){
                  dp[j]=dp[j]+dp[j-m];
              }
                ob.append(String.valueOf(dp[j]+" "));
            }
            System.out.println(ob.toString());
            System.exit(0);

    }

    public static int binary(long val,long[] arr){
        //    System.out.println("value "+ val);
        int i=0;
        int mid= 0;
        int e = arr.length;
        while(i<=e){
            //    System.out.println(i+ " "+e);

            mid = (i+e)/2;

            if(arr[mid]==val){

                return mid;
            }
            if(arr[mid]>val){

                e=mid-1;
                continue;
            }
            i=mid+1;

        }
        // System.out.println(mid);
        return mid;
    }

    public static void arrinit(String[] a,long[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Long.parseLong(a[i]);
        }
    }
    public static void arrinit(String[] a,int[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Integer.parseInt(a[i]);
        }
    }

    static double findRoots(int a, int b, int c) {
        // If a is 0, then equation is not
        //quadratic, but linear

        int d = b * b - 4 * a * c;
        double sqrt_val = Math.sqrt(Math.abs(d));

        // System.out.println("Roots are real and different \n");

        return Math.max((double) (-b + sqrt_val) / (2 * a),
                (double) (-b - sqrt_val) / (2 * a));

    }

    public static String cin() throws Exception {
        return br.readLine();
    }

    public static String[] cinA() throws Exception {
        return br.readLine().split(" ");
    }
    public static String[] cinA(int x) throws Exception{
        return br.readLine().split("");
    }

    public static String ToString(Long x) {
        return Long.toBinaryString(x);
    }

    public static void cout(String s) {
        System.out.println(s);
    }

    public static Integer cinI() throws Exception {
        return Integer.parseInt(br.readLine());
    }

    public static int getI(String s) throws Exception {
        return Integer.parseInt(s);
    }

    public static long getL(String s) throws Exception {
        return Long.parseLong(s);
    }

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

    public static void coutI(int x) {
        System.out.println(String.valueOf(x));
    }

    public static void coutI(long x) {
        System.out.println(String.valueOf(x));
    }

    public static Long cinL() throws Exception {
        return Long.parseLong(br.readLine());
    }

    public static void arrInit(String[] arr, int[] arr1) throws Exception {
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = getI(arr[i]);
        }

    }
}

class range {
    int l;
    int r;
    int diff;

    public range(int l, int r, int diff) {
        this.l = l;
        this.r = r;
        this.diff = diff;
    }
}

class sortRange implements Comparator<range> {

    @Override
    public int compare(range range, range t1) {
        if (range.diff != t1.diff)
            return t1.diff - range.diff;
        return range.l - t1.l;

    }}


import java.io.*;
import java.util.*;
import java.util.logging.Logger;

public class Main {
    static BufferedReader br;

    public static void main(String[] args) throws Exception {
        br = new BufferedReader(new InputStreamReader(System.in));
        String[] arr = cinA();
        int n =  getI(arr[0]);
        int m = getI(arr[1]);
        String[] data = cinA();
        int [] a = new int[n];
        for(int i=0;i<n;i++){
            a[i]=getI(data[i]);
        }
        Arrays.sort(a);
        int[] pre  = new int[n];
        pre[0]=a[0];
        for(int j=1;j<n;j++){
            pre[j]=pre[j-1]+a[j];
        }
        if(m!=1) {
            int[] dp = new int[n];
            StringBuilder ob=  new StringBuilder();
            dp[0]=pre[0];
            ob.append(String.valueOf(dp[0]+" "));
            for (int j = 1; j < n; j++) {
              dp[j]=pre[j];
              if(j-m>=0){
                  dp[j]=dp[j]+dp[j-m];
              }
                ob.append(String.valueOf(dp[j]+" "));
            }
            System.out.println(ob.toString());
            System.exit(0);
        }
        StringBuilder ob = new StringBuilder();
        for(int j=0;j<n;j++){
            ob.append(String.valueOf(pre[j]+" "));
        }
        System.out.println(ob.toString());
        System.exit(0);
    }

    public static int binary(long val,long[] arr){
        //    System.out.println("value "+ val);
        int i=0;
        int mid= 0;
        int e = arr.length;
        while(i<=e){
            //    System.out.println(i+ " "+e);

            mid = (i+e)/2;

            if(arr[mid]==val){

                return mid;
            }
            if(arr[mid]>val){

                e=mid-1;
                continue;
            }
            i=mid+1;

        }
        // System.out.println(mid);
        return mid;
    }

    public static void arrinit(String[] a,long[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Long.parseLong(a[i]);
        }
    }
    public static void arrinit(String[] a,int[] b)throws Exception{
        for(int i=0;i<a.length;i++){
            b[i]=Integer.parseInt(a[i]);
        }
    }

    static double findRoots(int a, int b, int c) {
        // If a is 0, then equation is not
        //quadratic, but linear

        int d = b * b - 4 * a * c;
        double sqrt_val = Math.sqrt(Math.abs(d));

        // System.out.println("Roots are real and different \n");

        return Math.max((double) (-b + sqrt_val) / (2 * a),
                (double) (-b - sqrt_val) / (2 * a));

    }

    public static String cin() throws Exception {
        return br.readLine();
    }

    public static String[] cinA() throws Exception {
        return br.readLine().split(" ");
    }
    public static String[] cinA(int x) throws Exception{
        return br.readLine().split("");
    }

    public static String ToString(Long x) {
        return Long.toBinaryString(x);
    }

    public static void cout(String s) {
        System.out.println(s);
    }

    public static Integer cinI() throws Exception {
        return Integer.parseInt(br.readLine());
    }

    public static int getI(String s) throws Exception {
        return Integer.parseInt(s);
    }

    public static long getL(String s) throws Exception {
        return Long.parseLong(s);
    }

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

    public static void coutI(int x) {
        System.out.println(String.valueOf(x));
    }

    public static void coutI(long x) {
        System.out.println(String.valueOf(x));
    }

    public static Long cinL() throws Exception {
        return Long.parseLong(br.readLine());
    }

    public static void arrInit(String[] arr, int[] arr1) throws Exception {
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = getI(arr[i]);
        }

    }
}

class range {
    int l;
    int r;
    int diff;

    public range(int l, int r, int diff) {
        this.l = l;
        this.r = r;
        this.diff = diff;
    }
}

class sortRange implements Comparator<range> {

    @Override
    public int compare(range range, range t1) {
        if (range.diff != t1.diff)
            return t1.diff - range.diff;
        return range.l - t1.l;

    }}


import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.text.DecimalFormat;
import java.lang.Math;
import java.util.Iterator;
import java.util.TreeSet;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.*;
public class C1343{
	public static PrintWriter out = new PrintWriter (new BufferedOutputStream(System.out));
	static long MOD = (long)(1e9+7);
	static FastReader sc = new FastReader();
	static int pInf = Integer.MAX_VALUE;
	static int nInf = Integer.MIN_VALUE;
	static String s;
	public static void main(String[] args){
		int t = 1;
		while(t-->0){
		    int n = sc.nextInt();
		    int m = sc.nextInt();
		    long[] a = new long[n];
		    long[] sum = new long[n+1];
		    long[] ans = new long[n+1];
		    for(int i = 0; i < n; i++){
		        a[i] = sc.nextInt();
		    }
		    sort(a,0,n-1);
		    for(int i = 1; i <n+1; i++){
		        sum[i] = sum[i-1]+a[i-1];
		        int cur = i;
		        int k = 1;
		        while(cur>0){
		            ans[i] += (sum[cur]-sum[Math.max(cur-m,0)])*k;
		            k++;
		            cur = cur-m;
		        }
		    }
		    StringBuffer sb = new StringBuffer("");
		    for(int i = 1; i < n+1; i++){
		        sb.append(ans[i]+" ");
		    }
		    out.print(sb);
	//	    out.println();
	//	    for(int i = 1; i < n+1; i++){
	//	        out.print(sum[i]+" ");
	//	    }
		}
		out.close();
	}
	public static boolean check(int x , String ss){

	    if(x+2 >= s.length()-1){
	        return false;
	    }
	    for(int i = x+2 ; i < s.length()-1; i++){
	        if(s.charAt(i)==ss.charAt(0) && s.charAt(i+1)==ss.charAt(1)){
	            return true;
	        }
	    }
	    return false;
	}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Integer.lowestOneBit(i)   Equals k where k is the position of the first one in the binary
//Integer.highestOneBit(i)  Equals k where k is the position of the last one in the binary
//Integer.bitCount(i)       returns the number of one-bits
//Collections.sort(A,(p1,p2)->(int)(p2.x-p1.x)) To sort ArrayList in descending order wrt values of x.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Pair Class
	static class Pair implements Comparable<Pair>{
		int x;
		int y;
		public Pair(int x, int y) {
			this.x = x;
			this.y = y;
		}
		@Override
		public int compareTo(Pair o) {
			// TODO Auto-generated method stub
			if(this.x==o.x){
			    return (this.y-o.y);
			}
			return (this.x-o.x);
		}
	}
//Merge Sort
	static void merge(long arr[], int l, int m, int r)
    {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        long L[] = new long [n1];
        long R[] = new long [n2];

        /*Copy data to temp arrays*/
        for (int i=0; i<n1; ++i)
            L[i] = arr[l + i];
        for (int j=0; j<n2; ++j)
            R[j] = arr[m + 1+ j];

        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2)
        {
            if (L[i] <= R[j])
            {
                arr[k] = L[i];
                i++;
            }
            else
            {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1)
        {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2)
        {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    static void sort(long arr[], int l, int r)
    {
        if (l < r)
        {
            // Find the middle point
            int m = (l+r)/2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr , m+1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }
//Brian Kernighan’s Algorithm
    static long countSetBits(long n){
        if(n==0) return 0;
        return 1+countSetBits(n&(n-1));
    }
//Factorial
    static long factorial(long n){
        if(n==1) return 1;
        if(n==2) return 2;
        if(n==3) return 6;
        return n*factorial(n-1);
    }
//Euclidean Algorithm
    static long gcd(long A,long B){
        if(B==0) return A;
        return gcd(B,A%B);
    }
//Modular Exponentiation
    static long fastExpo(long x,long n){
        if(n==0) return 1;
        if((n&1)==0) return fastExpo((x*x)%MOD,n/2)%MOD;
        return ((x%MOD)*fastExpo((x*x)%MOD,(n-1)/2))%MOD;
    }
//AKS Algorithm
    static boolean isPrime(long n){
        if(n<=1) return false;
        if(n<=3) return true;
        if(n%2==0 || n%3==0) return false;
        for(int i=5;i*i<=n;i+=6)
            if(n%i==0 || n%(i+2)==0) return false;
        return true;
    }
//Reverse an array
    static <T> void reverse(T arr[],int l,int r){
    	Collections.reverse(Arrays.asList(arr).subList(l, r));
    }
//Sieve of eratosthenes
    static int[] findPrimes(int n){
        boolean isPrime[]=new boolean[n+1];
        ArrayList<Integer> a=new ArrayList<>();
        int result[];
        Arrays.fill(isPrime,true);
        isPrime[0]=false;
        isPrime[1]=false;
        for(int i=2;i*i<=n;++i){
            if(isPrime[i]==true){
                for(int j=i*i;j<=n;j+=i) isPrime[j]=false;
            }
        }
        for(int i=0;i<=n;i++) if(isPrime[i]==true) a.add(i);
        result=new int[a.size()];
        for(int i=0;i<a.size();i++) result[i]=a.get(i);
        return result;

    }
//Euler Totent function
    static long countCoprimes(long n){
        ArrayList<Long> prime_factors=new ArrayList<>();
        long x=n,flag=0;
        while(x%2==0){
            if(flag==0) prime_factors.add(2L);
            flag=1;
            x/=2;
        }
        for(long i=3;i*i<=x;i+=2){
            flag=0;
            while(x%i==0){
                if(flag==0) prime_factors.add(i);
                flag=1;
                x/=i;
            }
        }
        if(x>2) prime_factors.add(x);
        double ans=(double)n;
        for(Long p:prime_factors){
            ans*=(1.0-(Double)1.0/p);
        }
        return (long)ans;
    }
	public static int bSearch(int n,ArrayList<Integer> A){
	    int s = 0;
	    int e = A.size()-1;
	    while(s<=e){
	        int m = s+(e-s)/2;
	        if(A.get(m)==(long)n){
	            return A.get(m);
	        }
	        else if(A.get(m)>(long)n){
	            e = m-1;
	        }
	        else{
	            s = m+1;
	        }
	    }
	    return A.get(e);
	}
	static long modulo = (long)1e9+7;
	public static long modinv(long x){
	    return modpow(x, modulo-2);
	}
	public static long modpow(long a, long b){
	    if(b==0){
	        return 1;
	    }
	    long x = modpow(a, b/2);
	    x = (x*x)%modulo;
	    if(b%2==1){
	        return (x*a)%modulo;
	    }
	    return x;
	}
	public static class FastReader {
		BufferedReader br;
		StringTokenizer st;
		//it reads the data about the specified point and divide the data about it ,it is quite fast
		//than using direct

		public FastReader() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (Exception r) {
					r.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());//converts string to integer
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		String nextLine() {
			String str = "";
			try {
				str = br.readLine();
			} catch (Exception r) {
				r.printStackTrace();
			}
			return str;
		}
	}
}