#include<bits/stdc++.h>

#define MOD 1000000007
#define MAX 100005
#define ll long long
#define slld(t) scanf("%lld",&t)
#define sd(t) scanf("%d",&t)
#define ss(x) scanf("%s",x)
#define pd(t) printf("%d\n",t)
#define plld(t) printf("%lld\n",t)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define tr(container,it) for(typeof(container.begin()) it=container.begin();it!=container.end();it++)
#define mp(a,b) make_pair(a,b)
#define FF first
#define SS second
#define pb(x) push_back(x)
#define vi vector<int>
#define vpii vector<pii >
#define vll vector<ll>
#define clr(x) memset(x,0,sizeof(x))

#define FILEIO(name) \
    freopen(name".in", "r", stdin); \
    freopen(name".out", "w", stdout);

using namespace std;

ll power(ll a,ll b,ll m){
	ll x=1%m; a%=m;
	while(b){
		if((1&b)) x = x * a % m;
		a = a * a % m;
		b >>= 1;
	}
	return x;
}

int a[MAX];
int mark[MAX];

int prev[MAX];

int main(){
	int n;sd(n);
	clr(mark);
	for(int i=1;i<=n;i++){
		sd(a[i]);
		prev[i] = mark[a[i]];
		mark[a[i]] = i;
	}

	ll ways = 0;
	for(int i=1;i<=n;i++){
		int lowl = prev[i]+1;
		int highr = n;

		ways += (i-lowl+1)*2LL*(highr-i);
		ways += (i-lowl)*2;
		ways++;
	}

	double ans = ways/(n*1.0*n);
	printf("%.8lf",ans);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
ll st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			lazy[p*2] += lazy[p];
			lazy[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) *1LL* lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
ll query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	ll ans=0;
	double tot = n* 1LL*(n);
	for(int i=n; i>=1; i--) {
		update(i, nxt[i] - 1, +1);
		ans += (query(i,n) - 1) ;
	}
	memset(lazy, 0, sizeof lazy);
	memset(st, 0, sizeof st);
	for(int i=1; i<=n; i++) {
		update(last[i] + 1, i, +1);
		ans += (query(1,i) - 1) ;
	}
	ans += n;
	double finalAns = ans / tot;

//	ans += (double)n / tot;
	printf("%.9f\n", finalAns);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
int st[N * 10];
int last[N], last2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			st[p*2] += lazy[p];
			st[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) * lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
int query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	double ans=0;
	double tot = n* (n);
	for(int i=n; i>=1; i--) {
		update(last[i] + 1, i, +1);
		ans += (1.0 / tot) * (query(i,n) - 1) * 2;
	}
	ans += (double)n / tot;
	printf("%.9f\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
ll st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			lazy[p*2] += lazy[p];
			lazy[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) *1LL* lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
ll query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	double ans=0;
	double tot = n* 1LL*(n);
	for(int i=n; i>=1; i--) {

		update(i, nxt[i] - 1, +1);
		ll f = query(i,n);
		ans += (1.0 / tot) * (query(i,n) - 1) ;
	}
	memset(lazy, 0, sizeof lazy);
	memset(st, 0, sizeof st);
	for(int i=1; i<=n; i++) {
		update(last[i] + 1, i, +1);
		ll f = query(1, i);
		ans += (1.0 / tot) * (query(1,i) - 1) ;
	}

	ans += (n / tot);

//	ans += (double)n / tot;
	printf("%.9f\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
ll st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			st[p*2] += lazy[p];
			st[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) *1LL* lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
ll query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	double ans=0;
	double tot = n* 1LL*(n);
	for(int i=n; i>=1; i--) {

		update(i, nxt[i] - 1, +1);
		ll f = query(i,n);
		ans += (1.0 / tot) * (query(i,n) - 1) ;
	}
	memset(lazy, 0, sizeof lazy);
	memset(st, 0, sizeof st);
	for(int i=1; i<=n; i++) {
		update(last[i] + 1, i, +1);
		ll f = query(1, i);
		ans += (1.0 / tot) * (query(1,i) - 1) ;
	}

	ans += (n / tot);

//	ans += (double)n / tot;
	printf("%.9f\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
ll st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			st[p*2] += lazy[p];
			st[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) *1LL* lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
ll query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	double ans=0;
	double tot = n* (n);
	for(int i=n; i>=1; i--) {

		update(i, nxt[i] - 1, +1);
		ll f = query(i,n);
		ans += (1.0 / tot) * (f - 1) ;
	}
	memset(lazy, 0, sizeof lazy);
	memset(st, 0, sizeof st);
	for(int i=1; i<=n; i++) {
		update(last[i] + 1, i, +1);
		ll f = query(1, i);
		ans += (1.0 / tot) * (query(1,i) - 1) ;
	}

	ans += (n / tot);

//	ans += (double)n / tot;
	printf("%.9f\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
ll st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			lazy[p*2] += lazy[p];
			lazy[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) *1LL* lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
ll query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	ll ans=0;
	double tot = n* 1LL*(n);
	for(int i=n; i>=1; i--) {
		update(i, nxt[i] - 1, +1);
		ans += (query(i,n) - 1) * 2;
	}
//	memset(lazy, 0, sizeof lazy);
//	memset(st, 0, sizeof st);
//	for(int i=1; i<=n; i++) {
//		update(last[i] + 1, i, +1);
//		ans += (query(1,i) - 1) ;
//	}
	ans += n;
	double finalAns = ans / tot;

//	ans += (double)n / tot;
	printf("%.9f\n", finalAns);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, pair<int,int> > pp;
#define N 1000006
int n;
int a[N];
int st[N * 10];
int last[N], last2[N];
int nxt[N], nxt2[N];
int lazy[N * 10];
void pushLazy(int p, int l, int r) {
	if (lazy[p]) {
		if (l != r) {
			st[p*2] += lazy[p];
			st[p*2+1] += lazy[p];
		}
		st[p] += (r - l + 1) * lazy[p];
		lazy[p] = 0;
	}
}
void update(int i, int j, int val, int p = 1, int l = 1, int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return ;
	if (i <= l && j >= r) { lazy[p] = val; pushLazy(p,l,r); return ; }
	int mid = (l+r) >> 1;
	update(i, j, val, p*2, l, mid);
	update(i, j, val, p*2+1, mid+1, r);
	st[p] = st[p*2] + st[p*2+1];
}
int query(int i, int j, int p = 1, int l =1 , int r = n) {
	pushLazy(p, l, r);
	if (i > r || j < l) return 0;
	if (i <= l && j >= r) return st[p];
	int mid = (l+r) >> 1;
	return query(i,j,p*2, l, mid) + query(i,j,p*2+1, mid+1, r);
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);

	for(int i=1; i<=n; i++) {
		last[i] = last2[a[i]];
		last2[a[i]] = i;
	}
	for(int i=0; i<N; i++) nxt2[a[i]] = n + 1;
	for(int i=n; i>=1; i--) {
		nxt[i] = nxt2[a[i]];
		nxt2[a[i]] = i;
	}
	double ans=0;
	double tot = n* (n);
	for(int i=n; i>=1; i--) {
		update(last[i] + 1, i, +1);
		ans += (1.0 / tot) * (query(i,n) - 1) ;
	}
	memset(lazy, 0, sizeof lazy);
	memset(st, 0, sizeof st);
	for(int i=1; i<=n; i++) {
		update(i, nxt[i] - 1, +1);
		ans += (1.0 / tot) * (query(1,i) - 1) ;
	}

	ans += (n / tot);

//	ans += (double)n / tot;
	printf("%.9f\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
const int MAX=1e6+5;
vector<int> vec[MAX];

int main()
{
	LL n;
	scanf("%lld",&n);
	for(int i=1;i<=1e6;i++)
	{
		vec[i].push_back(0);
	}
	for(int i=1;i<=n;i++)
	{
		int a;
		scanf("%d",&a);
		vec[a].push_back(i);
	}
	LL ans=0;
	for(int i=1;i<=1e6;i++)
	{
		if(vec[i].size()>1)
		{
			vec[i].push_back(n+1);
			LL cur=n*n;
			for(int j=1;j<vec[i].size();j++)
			{
				LL dif=vec[i][j]-vec[i][j-1]-1;
				cur-=(dif*dif);
			}
			ans+=cur;
		}
	}
	printf("%lf\n",(double)ans/(double)(n*n));
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int MAXN = 5e4+5;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;

template <class T>
inline bool read(T &ret) {
   char c; int sgn;
   if(c=getchar(),c==EOF) return 0; //EOF
   while(c!='-'&&(c<'0'||c>'9')) c=getchar();
   sgn=(c=='-')?-1:1;
   ret=(c=='-')?0:(c-'0');
   while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
   ret*=sgn;
   return 1;
}

int Hash[1000005], cnt;
vector<int> v[1000005];

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    //ios::sync_with_stdio(false);
    //cin.tie(NULL);
    //cout.tie(NULL);
    int n;
    read(n);
    memset(Hash, 0, sizeof(Hash));
    cnt = 0;
    for(int i = 1; i <= n; ++i) {
        int x;
        read(x);
        if(Hash[x]) v[Hash[x]].push_back(i);
        else {
            Hash[x] = ++cnt;
            v[cnt].clear();
            v[cnt].push_back(0);
            v[cnt].push_back(i);
        }
    }
    ll ans = n * n * cnt;
    for(int i = 1; i <= cnt; ++i) {
        v[i].push_back(n+1);
        for(int j = 1; j < v[i].size(); ++j) {
            ll d = v[i][j] - v[i][j-1] - 1;
            if(d == 0) continue;
            ans -= d * d;
        }
    }
    printf("%.6f\n", (double)ans / (n * n));
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int MAXN = 5e4+5;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;

template <class T>
inline bool read(T &ret) {
   char c; int sgn;
   if(c=getchar(),c==EOF) return 0; //EOF
   while(c!='-'&&(c<'0'||c>'9')) c=getchar();
   sgn=(c=='-')?-1:1;
   ret=(c=='-')?0:(c-'0');
   while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
   ret*=sgn;
   return 1;
}

int Hash[1000005], cnt;
vector<int> v[1000005];

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    //ios::sync_with_stdio(false);
    //cin.tie(NULL);
    //cout.tie(NULL);
    int n;
    read(n);
    memset(Hash, 0, sizeof(Hash));
    cnt = 0;
    for(int i = 1; i <= n; ++i) {
        int x;
        read(x);
        if(Hash[x]) v[Hash[x]].push_back(i);
        else {
            Hash[x] = ++cnt;
            v[cnt].clear();
            v[cnt].push_back(0);
            v[cnt].push_back(i);
        }
    }
    ll ans = (ll)n * n * cnt;
    for(int i = 1; i <= cnt; ++i) {
        v[i].push_back(n+1);
        for(int j = 1; j < v[i].size(); ++j) {
            ll d = v[i][j] - v[i][j-1] - 1;
            if(d == 0) continue;
            ans -= d * d;
        }
    }
    printf("%.6f\n", (double)ans / ((ll)n * n));
    return 0;
}


#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
long long n, a, high = 0;
long long total, len;
vector<long long> v[1000001];
int main (){
	scanf("%I64d", &n);
	for (int i = 0; i < n; i++){
		scanf("%I64d", &a);
		v[a].push_back(i);
		if (high < a)
			high = a;
	}
	total = n;
	for (int i = 1; i <= high; i++){
		len = v[i].size();
		sort(v[i].begin(), v[i].end());
		if (len > 0){
			total += n * (n - 1);
			total -= v[i][0] * (v[i][0] - 1);
			total -= (n - 1 - v[i][len - 1]) * (n - 2 - v[i][len - 1]);
			for (int j = 1; j < len; j++)
				total -= (v[i][j] - v[i][j - 1] - 1) * (v[i][j] - v[i][j - 1] - 2);
		}
	}
	printf("%.6lf\n", (total + .0) / n / n);
	return 0;
}


#include <algorithm>
#include <cstdio>
using namespace std;

struct num{
	long long a;
	long long index;
};

long long n, left, right;
long long total, len;
num elem[1000001];

bool compare(num x, num y){
	return x.a < y.a || x.a == y.a && x.index < y.index;
}

int main (){
	scanf("%I64d", &n);
	for (int i = 0; i < n; i++){
		scanf("%I64d", &elem[i].a);
		elem[i].index = i;
	}
	sort(elem, elem + n, compare);
	total = n;
	left = 0;
	for (int i = 0; i <= n; i++){
		if (elem[i].a != elem[left].a || i == n){
			right = i - 1;
			len = right - left + 1;
			total += n * (n - 1);
			total -= elem[left].index * (elem[left].index - 1);
			total -= (n - 1 - elem[right].index) * (n - 2 - elem[right].index);
			for (int j = left; j < right; j++)
				total -= (elem[j + 1].index - elem[j].index - 1) * (elem[j + 1].index - elem[j].index - 2);
			left = i;
		}
	}
	printf("%.6lf\n", (total + .0) / n / n);
	return 0;
}


//19
//21:11
//21:42
//22:07
#include<cstdio>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 200001;
const int sqtn = 501;

int n, q;
int c[maxn];
set<int> pos[maxn];

void init();
void modify(int l, int r, int d);
int cal();
void changea(int x, int d);
void change(int x, int d);

int main() {
	scanf("%d%d", &n, &q);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &c[i]);
		pos[c[i]].insert(i);
	}
	init();
	int ans = n - cal();
	printf("%d\n", ans);
	for (int i = 1; i <= q; i++) {
		int x, d;
		scanf("%d%d", &x, &d);
		change(x, d);
		int ans = n - cal();
		printf("%d\n", ans);
	}
	return 0;
}

int a[maxn], b[maxn];
int bsz, bcnt;
int bel[maxn];
int st[sqtn], en[sqtn];
int delta[sqtn];
int minb[sqtn], idl[sqtn], idr[sqtn];
int cur[sqtn];
int maxal[sqtn], maxar[sqtn], maxa[sqtn];

void init() {
	for (int i = 1; i < maxn; i++) {
		if (pos[i].empty()) continue;
		int l = *(pos[i].begin());
		int r = *(pos[i].rbegin());
		a[l] = pos[i].size();
		b[l + 1] += 1;
		b[r + 1] -= 1;
	}
	for (int i = 1; i <= n; i++) {
		b[i] += b[i - 1];
	}
	bsz = sqrt(n);
	for (int i = 1; i <= n; i++) {
		bel[i] = (i - 1) / bsz + 1;
		if (bel[i] != bel[i - 1]) {
			bcnt++;
			en[bcnt - 1] = i - 1;
			st[bcnt] = i;
		}
	}
	en[bcnt] = n;
	for (int k = 1; k <= bcnt; k++) {
		minb[k] = b[st[k]];
		for (int i = st[k]; i <= en[k]; i++) {
			minb[k] = min(minb[k], b[i]);
		}
		for (int i = st[k]; i <= en[k]; i++) {
			if (b[i] == minb[k]) {
				idl[k] = i;
				break;
			}
			maxal[k] = max(maxal[k], a[i]);
		}
		for (int i = en[k]; i >= st[k]; i--) {
			maxar[k] = max(maxar[k], a[i]);
			if (b[i] == minb[k]) {
				idr[k] = i;
				break;
			}
		}
		for (int i = st[k]; i <= en[k]; i++) {
			maxa[k] = max(maxa[k], a[i]);
		}
		int maxa = 0;
		for (int i = idl[k]; i <= idr[k]; i++) {
			if (b[i] == minb[k]) {
				cur[k] += maxa;
				maxa = 0;
			}
			maxa = max(maxa, a[i]);
		}
	}
}

void macro(int k, int d) {
	minb[k] += d;
	delta[k] += d;
}

void micro(int k, int l, int r, int d) {
	for (int i = st[k]; i <= en[k]; i++) {
		b[i] += delta[k];
	}
	for (int i = l; i <= r; i++) {
		b[i] += d;
	}
	delta[k] = 0;
	minb[k] = b[st[k]];
	for (int i = st[k]; i <= en[k]; i++) {
		minb[k] = min(minb[k], b[i]);
	}
	maxal[k] = maxar[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		if (b[i] == minb[k]) {
			idl[k] = i;
			break;
		}
		maxal[k] = max(maxal[k], a[i]);
	}
	for (int i = en[k]; i >= st[k]; i--) {
		maxar[k] = max(maxar[k], a[i]);
		if (b[i] == minb[k]) {
			idr[k] = i;
			break;
		}
	}
	maxa[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		maxa[k] = max(maxa[k], a[i]);
	}
	cur[k] = 0;
	int maxa = 0;
	for (int i = idl[k]; i <= idr[k]; i++) {
		if (b[i] == minb[k]) {
			cur[k] += maxa;
			maxa = 0;
		}
		maxa = max(maxa, a[i]);
	}
}

void modify(int l, int r, int d) {
	//printf("modify %d %d %d\n", l, r, d);
	if (l > r) return;
	for (int k = 1; k <= bcnt; k++) {
		if (st[k] >= l && en[k] <= r) macro(k, d);
		else if (st[k] <= r && en[k] >= l) micro(k, max(st[k], l), min(en[k], r), d);
	}
}

int cal() {
	int ans = 0;
	int maxa = 0;
	for (int k = 1; k <= bcnt; k++) {
		if (minb[k] != 0) {
			maxa = max(maxa, ::maxa[k]);
			continue;
		}
		ans += cur[k];
		maxa = max(maxa, maxal[k]);
		ans += maxa;
		maxa = maxar[k];
	}
	ans += maxa;
	return ans;
}

void changea(int x, int d) {
	a[x] = d;
	int k = bel[x];
	maxal[k] = maxar[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		if (b[i] == minb[k]) break;
		maxal[k] = max(maxal[k], a[i]);
	}
	for (int i = en[k]; i >= st[k]; i--) {
		maxar[k] = max(maxar[k], a[i]);
		if (b[i] == minb[k]) break;
	}
	maxa[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		maxa[k] = max(maxa[k], a[i]);
	}
	cur[k] = 0;
	int maxa = 0;
	for (int i = idl[k]; i <= idr[k]; i++) {
		if (b[i] == minb[k]) {
			cur[k] += maxa;
			maxa = 0;
		}
		maxa = max(maxa, a[i]);
	}
}

void change(int x, int d) {
	int c = ::c[x];
	int l = *(pos[c].begin());
	int r = *(pos[c].rbegin());
	changea(l, 0);
	modify(l + 1, r, -1);
	pos[c].erase(x);
	if (!pos[c].empty()) {
		l = *(pos[c].begin());
		r = *(pos[c].rbegin());
		changea(l, pos[c].size());
		modify(l + 1, r, 1);
	}

	c = ::c[x] = d;
	if (!pos[c].empty()) {
		l = *(pos[c].begin());
		r = *(pos[c].rbegin());
		changea(l, 0);
		modify(l + 1, r, -1);
	}
	pos[c].insert(x);
	l = *(pos[c].begin());
	r = *(pos[c].rbegin());
	changea(l, pos[c].size());
	modify(l + 1, r, 1);
}


//19
#include<cstdio>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 200002;
const int sqtn = 501;

int n, q;
int c[maxn];
set<int> pos[maxn];

void init();
void insert(int c, int i);
void remove(int c, int i);
int cal();
void print();

int main() {
	scanf("%d%d", &n, &q);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &c[i]);
		pos[c[i]].insert(i);
	}
	init();
	//print();
	int ans = n - cal();
	printf("%d\n", ans);
	for (int i = 1; i <= q; i++) {
		int x, d;
		scanf("%d%d", &x, &d);
		remove(c[x], x);
		c[x] = d;
		insert(c[x], x);
		//print();
		int ans = n - cal();
		printf("%d\n", ans);
	}
	return 0;
}

int a[maxn], b[maxn];
int bsz, bcnt;
int bel[maxn];
int st[sqtn], en[sqtn];
int delta[sqtn];
int minb[sqtn], idl[sqtn], idr[sqtn];
int cur[sqtn];
int maxal[sqtn], maxar[sqtn], maxa[sqtn];

void build(int k) {
	for (int i = st[k]; i <= en[k]; i++) {
		b[i] += delta[k];
	}
	delta[k] = 0;
	minb[k] = b[st[k]];
	for (int i = st[k]; i <= en[k]; i++) {
		minb[k] = min(minb[k], b[i]);
	}
	maxal[k] = maxar[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		if (b[i] == minb[k]) {
			idl[k] = i;
			break;
		}
		maxal[k] = max(maxal[k], a[i]);
	}
	for (int i = en[k]; i >= st[k]; i--) {
		maxar[k] = max(maxar[k], a[i]);
		if (b[i] == minb[k]) {
			idr[k] = i;
			break;
		}
	}
	maxa[k] = 0;
	for (int i = st[k]; i <= en[k]; i++) {
		maxa[k] = max(maxa[k], a[i]);
	}
	cur[k] = 0;
	int maxa = 0;
	for (int i = idl[k]; i <= idr[k]; i++) {
		if (b[i] == minb[k]) {
			cur[k] += maxa;
			maxa = 0;
		}
		maxa = max(maxa, a[i]);
	}
}

void init() {
	for (int i = 1; i < maxn; i++) {
		if (pos[i].empty()) continue;
		int l = *(pos[i].begin());
		int r = *(pos[i].rbegin());
		a[l] = pos[i].size();
		b[l + 1] += 1;
		b[r + 1] -= 1;
	}
	for (int i = 1; i <= n; i++) {
		b[i] += b[i - 1];
	}
	bsz = sqrt(n);
	for (int i = 1; i <= n; i++) {
		bel[i] = (i - 1) / bsz + 1;
		if (bel[i] != bel[i - 1]) {
			bcnt++;
			en[bcnt - 1] = i - 1;
			st[bcnt] = i;
		}
	}
	en[bcnt] = n;
	for (int k = 1; k <= bcnt; k++) {
		build(k);
	}
}

void macro(int k, int d) {
	minb[k] += d;
	delta[k] += d;
}

void micro(int k, int l, int r, int d) {
	for (int i = l; i <= r; i++) {
		b[i] += d;
	}
	build(k);
}

void modify(int l, int r, int d) {
	//printf("modify %d %d %d\n", l, r, d);
	if (l > r) return;
	for (int k = 1; k <= bcnt; k++) {
		if (st[k] >= l && en[k] <= r) macro(k, d);
		else if (st[k] <= r && en[k] >= l) micro(k, max(st[k], l), min(en[k], r), d);
	}
}

int cal() {
	int ans = 0;
	int maxa = 0;
	for (int k = 1; k <= bcnt; k++) {
		if (minb[k] != 0) {
			maxa = max(maxa, ::maxa[k]);
			continue;
		}
		ans += cur[k];
		maxa = max(maxa, maxal[k]);
		ans += maxa;
		maxa = maxar[k];
	}
	ans += maxa;
	return ans;
}

void insert(int c, int i) {
	int l, r;
	if (pos[c].size()) {
		l = *(pos[c].begin());
		r = *(pos[c].rbegin());
		a[l] = 0;
		build(bel[l]);
		modify(l + 1, r, -1);
	}
	pos[c].insert(i);
	l = *(pos[c].begin());
	r = *(pos[c].rbegin());
	a[l] = pos[c].size();
	build(bel[l]);
	modify(l + 1, r, 1);
}

void remove(int c, int i) {
	int l, r;
	l = *(pos[c].begin());
	r = *(pos[c].rbegin());
	a[l] = 0;
	build(bel[l]);
	modify(l + 1, r, -1);
	pos[c].erase(i);
	if (pos[c].size()) {
		l = *(pos[c].begin());
		r = *(pos[c].rbegin());
		a[l] = pos[c].size();
		build(bel[l]);
		modify(l + 1, r, 1);
	}
}

void print() {
	for (int i = 1; i <= n; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
	for (int i = 1; i <= n; i++) {
		printf("%d ", b[i] + delta[bel[i]]);
	}
	printf("\n");
}


/*mjytxdy!*/
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fir first
#define sec second
#define all(x) x.begin(),x.end()
#define size(x) ((int)x.size())
#define pii pair<int,int>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
#define inl inline
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define trv(i,u) for(int i=head[u];i;i=e[i].next)
#define lb(x) ((x)&(-(x)))
#define debug(x) cout<<#x":"<<x<<'\n'
#define myput puts("QaQ")
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
typedef long long ll;
template<class T>inl bool ylmin(T &a,T b){return a<b?0:(a=b,1);}
template<class T>inl bool ylmax(T &a,T b){return a>b?0:(a=b,1);}
template<class T>inl T abs(T x){return x<0?-x:x;}
inl char read(){
	static const int IO_LEN=1024*1024;
	static char buf[IO_LEN],*ioh,*iot;
	if(ioh==iot){
		iot=(ioh=buf)+fread(buf,1,IO_LEN,stdin);
		if(ioh==iot) return -1;
	}
	return *ioh++;
}
template<class T>inl void read(T &x){
	static int iosig;static char ioc;
	for(iosig=0,ioc=read();!isdigit(ioc);ioc=read()) if(ioc=='-') iosig=1;
	for(x=0;isdigit(ioc);ioc=read())x=(x<<1)+(x<<3)+(ioc^'0');
	if(iosig) x=-x;
}
const int MAXN = 2e5 + 10;
int n,q,a[MAXN],b[MAXN],c[MAXN];
set<int> Set[MAXN];
struct Segment{
	#define ls rt<<1
	#define rs rt<<1|1
	int Max[MAXN<<2],lmax[MAXN<<2],rmax[MAXN<<2],Min[MAXN<<2],sum[MAXN<<2],tag[MAXN<<2];
	inl void pushup(int rt){
		Max[rt]=max(Max[ls],Max[rs]);
		Min[rt]=min(Min[ls],Min[rs]);
		if(Min[ls]<Min[rs]){
			sum[rt]=sum[ls];
			lmax[rt]=lmax[ls];
			rmax[rt]=max(rmax[ls],Max[rs]);
		}
		else if(Min[ls]>Min[rs]){
			sum[rt]=sum[rs];
			lmax[rt]=max(lmax[rs],Max[ls]);
			rmax[rt]=rmax[rs];
		}
		else {
			sum[rt]=sum[ls]+sum[rs]+max(rmax[ls],lmax[rs]);
			lmax[rt]=lmax[ls];
			rmax[rt]=rmax[rs];
		}
	}
	inl void pushdown(int rt){
		Min[ls]+=tag[rt],Min[rs]+=tag[rt];
		tag[ls]+=tag[rt],tag[rs]+=tag[rt];
		tag[rt]=0;
	}
	inl void build(int rt,int l,int r){
		if(l==r) {
			Max[rt]=lmax[rt]=c[l];
			Min[rt]=b[l];
			return ;
		}
		int mid=l+r>>1;
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(rt);
	}
	inl void update1(int rt,int l,int r,int L,int R,int k){
		if(l>=L && r<=R){
			Min[rt]+=k,tag[rt]+=k;
			return ;
		}
		if(tag[rt]) pushdown(rt);
		int mid=l+r>>1;
		if(R<=mid) update1(ls,l,mid,L,R,k);
		else if(L>mid) update1(rs,mid+1,r,L,R,k);
		else update1(ls,l,mid,L,R,k),update1(rs,mid+1,r,L,R,k);
		pushup(rt);
	}
	inl void update2(int rt,int l,int r,int pos,int k){
		if(l==r){
			Max[rt]=lmax[rt]=k;
			return ;
		}
		if(tag[rt]) pushdown(rt);
		int mid=l+r>>1;
		if(pos<=mid) update2(ls,l,mid,pos,k);
		else update2(rs,mid+1,r,pos,k);
		pushup(rt);
	}
	inl int query(){
		if(Min[1]==0) return n-lmax[1]-rmax[1]-sum[1];
		else return n-Max[1];
	}
}mjy;
inl void del(int x){
	if(!size(Set[x])) return ;
	mjy.update2(1,1,n,*Set[x].begin(),0);
	if(size(Set[x])>1) mjy.update1(1,1,n,*Set[x].begin(),*Set[x].rbegin()-1,-1);
}
inl void add(int x){
	if(!size(Set[x])) return ;
	mjy.update2(1,1,n,*Set[x].begin(),size(Set[x]));
	if(size(Set[x])>1) mjy.update1(1,1,n,*Set[x].begin(),*Set[x].rbegin()-1,1);
}
int main(){
//	freopen("in.txt","r",stdin);
	read(n),read(q);
	rep(i,1,n) read(a[i]),Set[a[i]].insert(i);
	rep(i,1,2e5) {
		if(!size(Set[i])) continue;
		c[*Set[i].begin()]=size(Set[i]);
		b[*Set[i].begin()]++;
		b[*Set[i].rbegin()]--;
	}
	rep(i,1,n) b[i]+=b[i-1];
	mjy.build(1,1,n);
	printf("%d\n",mjy.query());
	rep(i,1,q){
		int p,x;
		read(p),read(x);
		del(a[p]);Set[a[p]].erase(p);add(a[p]);
		del(x);Set[x].insert(p);add(x);a[p]=x;
		printf("%d\n",mjy.query());
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

namespace SGT {

int addv[400000],minn[400000];
int maxl[400000],maxr[400000],maxn[400000];
int sumv[400000];

inline void pushdown(int o) {
  if (addv[o]) {
    addv[o*2]+=addv[o];addv[o*2+1]+=addv[o];
    minn[o*2]+=addv[o];minn[o*2+1]+=addv[o];
    addv[o]=0;
  }
}

inline void pushup(int o) {
  minn[o]=min(minn[o*2],minn[o*2+1]);
  maxn[o]=max(maxn[o*2],maxn[o*2+1]);
  if (minn[o*2]<minn[o*2+1]) {
    maxl[o]=maxl[o*2];
    maxr[o]=max(maxr[o*2],maxn[o*2+1]);
    sumv[o]=sumv[o*2];
  }
  else if (minn[o*2+1]<minn[o*2]) {
  	maxl[o]=max(maxn[o*2],maxl[o*2+1]);
  	maxr[o]=maxr[o*2+1];
  	sumv[o]=sumv[o*2+1];
  }
  else {
  	maxl[o]=maxl[o*2];
  	maxr[o]=maxr[o*2+1];
  	sumv[o]=sumv[o*2]+sumv[o*2+1]+max(maxr[o*2],maxl[o*2+1]);
  }
}

void update1(int l,int r,int o,int lx,int rx,int p) {
  if (l>=lx&&r<=rx) {
  	addv[o]+=p;
  	minn[o]+=p;
  }
  else {
  	pushdown(o);
  	int m=((l+r)>>1);
  	if (m>=lx) update1(l,m,o*2,lx,rx,p);
  	if (m<rx) update1(m+1,r,o*2+1,lx,rx,p);
  	pushup(o);
  }
}

void update2(int l,int r,int o,int p,int q) {
  if (l==r) maxn[o]=maxl[o]=q;
  else {
  	pushdown(o);
  	int m=((l+r)>>1);
  	if (m>=p) update2(l,m,o*2,p,q);
  	else update2(m+1,r,o*2+1,p,q);
  	pushup(o);
  }
}

int query() {
  return sumv[1]+maxl[1];
}

}

set <int> st[200005];
int n;

void erase(int x) {
  if (st[x].empty()) return;
  int u=*(st[x].begin()),v=*(st[x].rbegin());
  SGT::update2(1,n,1,u,0);
  if (u<v) SGT::update1(1,n,1,u,v-1,-1);
}

void insert(int x) {
  if (st[x].empty()) return;
  int u=*(st[x].begin()),v=*(st[x].rbegin());
  SGT::update2(1,n,1,u,st[x].size());
  if (u<v) SGT::update1(1,n,1,u,v-1,1);
}

int num[200005];

int main() {
  int m;
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++) {
  	int x;
  	scanf("%d",&x);
  	st[x].insert(i);
  	num[i]=x;
  }
  for(int i=1;i<=2e5;i++)
    insert(i);
  printf("%d\n",n-SGT::query());
  for(int i=1;i<=m;i++) {
  	int x,y;
  	scanf("%d%d",&x,&y);
  	erase(num[x]);
  	st[num[x]].erase(x);
  	insert(num[x]);
  	erase(y);
  	st[y].insert(x);
  	insert(y);
  	num[x]=y;
  	printf("%d\n",n-SGT::query());
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

namespace SGT {

int addv[800000],minn[800000];
int maxl[800000],maxr[800000],maxn[800000];
int sumv[800000];

inline void pushdown(int o) {
  if (addv[o]) {
    addv[o*2]+=addv[o];addv[o*2+1]+=addv[o];
    minn[o*2]+=addv[o];minn[o*2+1]+=addv[o];
    addv[o]=0;
  }
}

inline void pushup(int o) {
  minn[o]=min(minn[o*2],minn[o*2+1]);
  maxn[o]=max(maxn[o*2],maxn[o*2+1]);
  if (minn[o*2]<minn[o*2+1]) {
    maxl[o]=maxl[o*2];
    maxr[o]=max(maxr[o*2],maxn[o*2+1]);
    sumv[o]=sumv[o*2];
  }
  else if (minn[o*2+1]<minn[o*2]) {
  	maxl[o]=max(maxn[o*2],maxl[o*2+1]);
  	maxr[o]=maxr[o*2+1];
  	sumv[o]=sumv[o*2+1];
  }
  else {
  	maxl[o]=maxl[o*2];
  	maxr[o]=maxr[o*2+1];
  	sumv[o]=sumv[o*2]+sumv[o*2+1]+max(maxr[o*2],maxl[o*2+1]);
  }
}

void update1(int l,int r,int o,int lx,int rx,int p) {
  if (l>=lx&&r<=rx) {
  	addv[o]+=p;
  	minn[o]+=p;
  }
  else {
  	pushdown(o);
  	int m=((l+r)>>1);
  	if (m>=lx) update1(l,m,o*2,lx,rx,p);
  	if (m<rx) update1(m+1,r,o*2+1,lx,rx,p);
  	pushup(o);
  }
}

void update2(int l,int r,int o,int p,int q) {
  if (l==r) maxn[o]=maxl[o]=q;
  else {
  	pushdown(o);
  	int m=((l+r)>>1);
  	if (m>=p) update2(l,m,o*2,p,q);
  	else update2(m+1,r,o*2+1,p,q);
  	pushup(o);
  }
}

int query() {
  return sumv[1]+maxl[1];
}

}

set <int> st[200005];
int n;

void erase(int x) {
  if (st[x].empty()) return;
  int u=*(st[x].begin()),v=*(st[x].rbegin());
  SGT::update2(1,n,1,u,0);
  if (u<v) SGT::update1(1,n,1,u,v-1,-1);
}

void insert(int x) {
  if (st[x].empty()) return;
  int u=*(st[x].begin()),v=*(st[x].rbegin());
  SGT::update2(1,n,1,u,st[x].size());
  if (u<v) SGT::update1(1,n,1,u,v-1,1);
}

int num[200005];

int main() {
  int m;
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++) {
  	int x;
  	scanf("%d",&x);
  	st[x].insert(i);
  	num[i]=x;
  }
  for(int i=1;i<=2e5;i++)
    insert(i);
  printf("%d\n",n-SGT::query());
  for(int i=1;i<=m;i++) {
  	int x,y;
  	scanf("%d%d",&x,&y);
  	erase(num[x]);
  	st[num[x]].erase(x);
  	insert(num[x]);
  	erase(y);
  	st[y].insert(x);
  	insert(y);
  	num[x]=y;
  	printf("%d\n",n-SGT::query());
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define MN 200020

int n, q, a[MN];
set<int> occ[MN];

struct node {
    int mini, maxfreq, sum, l, r, lazy;
    node() : mini(0), maxfreq(0), sum(0), l(0), r(0), lazy(0) {}
};

node tree[8*MN];

void push_lazy(int id, int l, int r) {
    if(tree[id].lazy) {
        tree[id].mini += tree[id].lazy;
        if(l != r) {
            tree[id*2  ].lazy += tree[id].lazy;
            tree[id*2+1].lazy += tree[id].lazy;
        }
        tree[id].lazy = 0;
    }
}

node merge(node a, node b) {
    node c;
    if(a.mini == b.mini) {
        c.mini = a.mini;
        c.maxfreq = max(a.maxfreq, b.maxfreq);
        c.sum = a.sum + b.sum - min(a.r, b.l);
        c.l = a.l;
        c.r = b.r;
    } else if(a.mini < b.mini) {
        c.mini = a.mini;
        c.maxfreq = max(a.maxfreq, b.maxfreq);
        c.sum = a.sum - a.r + max(a.r, b.maxfreq);
        c.l = a.l;
        c.r = max(a.r, b.maxfreq);
    } else {
        c.mini = b.mini;
        c.maxfreq = max(a.maxfreq, b.maxfreq);
        c.sum = b.sum - b.l + max(b.l, a.maxfreq);
        c.l = max(b.l, a.maxfreq);
        c.r = b.r;
    }
    return c;
}

void upd_range(int id, int l, int r, int lq, int rq, int delta) {
    push_lazy(id, l, r);
    if(rq < l || r < lq) return;
    if(lq <= l && r <= rq) {
        tree[id].lazy += delta;
        push_lazy(id, l, r);
    } else {
        int m = (l + r) / 2;
        upd_range(id*2  , l,   m, lq, rq, delta);
        upd_range(id*2+1, m+1, r, lq, rq, delta);
        tree[id] = merge(tree[id*2], tree[id*2+1]);
    }
}

void upd_freq(int id, int l, int r, int x, int val) {
    push_lazy(id, l, r);
    if(x < l || r < x) return;
    if(l == r) {
        tree[id].maxfreq = tree[id].sum = tree[id].l = tree[id].r = val;
    } else {
        int m = (l + r) / 2;
        upd_freq(id*2  , l,   m, x, val);
        upd_freq(id*2+1, m+1, r, x, val);
        tree[id] = merge(tree[id*2], tree[id*2+1]);
    }
}

int query() {
    if(tree[1].mini == 0) return tree[1].sum;
    return tree[1].maxfreq;
}

int main() {
    scanf("%d %d", &n, &q);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        occ[a[i]].insert(i);
    }

    for(int i = 0; i < MN; i++) {
        if(occ[i].size() >= 1) {
            upd_range(1, 1, 2*n, 2**occ[i].begin(), 2**occ[i].rbegin(), 1);
            upd_freq(1, 1, 2*n, 2**occ[i].begin(), occ[i].size());
        }
    }

    printf("%d\n", n - query());

    for(int i = 0; i < q; i++) {
        int p, x, y;
        scanf("%d %d", &p, &x);
        y = a[p];

        if(occ[y].size() >= 1) {
            upd_range(1, 1, 2*n, 2**occ[y].begin(), 2**occ[y].rbegin(), -1);
            upd_freq(1, 1, 2*n, 2**occ[y].begin(), 0);
        }
        occ[y].erase(p);
        if(occ[y].size() >= 1) {
            upd_range(1, 1, 2*n, 2**occ[y].begin(), 2**occ[y].rbegin(), 1);
            upd_freq(1, 1, 2*n, 2**occ[y].begin(), occ[y].size());
        }

        /// <<<<<<<<<

        if(occ[x].size() >= 1) {
            upd_range(1, 1, 2*n, 2**occ[x].begin(), 2**occ[x].rbegin(), -1);
            upd_freq(1, 1, 2*n, 2**occ[x].begin(), 0);
        }
        occ[x].insert(p);
        if(occ[x].size() >= 1) {
            upd_range(1, 1, 2*n, 2**occ[x].begin(), 2**occ[x].rbegin(), 1);
            upd_freq(1, 1, 2*n, 2**occ[x].begin(), occ[x].size());
        }

        a[p] = x;
        printf("%d\n", n - query());
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

set<int> st[200010];

int num[200010],n,q;

inline int rd()
{
	int x=0;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar());
	for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x;
}

inline void print(int x)
{
	static char s[233];
	if (!x) { putchar('0');putchar('\n');return; }
	int tot=0;
	for (;x;x/=10) s[++tot]=x%10+'0';
	for (;tot;tot--) putchar(s[tot]);
	putchar('\n');
}

int mn[800010],mx[800010],smn[800010],sl[800010],sr[800010],tag[800010];

inline void pushup(const int &o)
{
	mx[o]=max(mx[o<<1],mx[o<<1|1]);
	if (mn[o<<1]<mn[o<<1|1])
	{
		mn[o]=mn[o<<1];smn[o]=smn[o<<1];
		sl[o]=sl[o<<1];sr[o]=max(sr[o<<1],mx[o<<1|1]);
	}
	else if (mn[o<<1|1]<mn[o<<1])
	{
		mn[o]=mn[o<<1|1];smn[o]=smn[o<<1|1];
		sl[o]=max(mx[o<<1],sl[o<<1|1]);sr[o]=sr[o<<1|1];
	}
	else
	{
		mn[o]=mn[o<<1];smn[o]=smn[o<<1]+smn[o<<1|1]+max(sr[o<<1],sl[o<<1|1]);
		sl[o]=sl[o<<1];sr[o]=sr[o<<1|1];
	}
}

inline void gao(const int &o,const int &hh) { mn[o]+=hh;tag[o]+=hh; }

inline void pushdown(const int &o)
{
	if (!tag[o]) return;
	gao(o<<1,tag[o]);gao(o<<1|1,tag[o]);
	tag[o]=0;
}

inline void update(int o,int l,int r,int x,int y)
{
	if (l==r) { mx[o]+=y;sl[o]+=y;return; }
	pushdown(o);
	int mid=(l+r)>>1;
	if (x<=mid) update(o<<1,l,mid,x,y);
	else update(o<<1|1,mid+1,r,x,y);
	pushup(o);
}

inline void modify(int o,int l,int r,int x,int y,int hh)
{
	if (l>=x&&r<=y) { gao(o,hh);return; }
	pushdown(o);
	int mid=(l+r)>>1;
	if (x<=mid) modify(o<<1,l,mid,x,y,hh);
	if (y>mid) modify(o<<1|1,mid+1,r,x,y,hh);
	pushup(o);
}

inline void del(int x,int y)
{
	if (st[y].size()==1)
	{
		update(1,1,n,*st[y].begin(),-1);
		st[y].clear();
		return;
	}
	if (x==*st[y].begin())
	{
		set<int>::iterator it=st[y].begin();it++;
		modify(1,1,n,x,(*it)-1,-1);
		update(1,1,n,x,-st[y].size());
		update(1,1,n,*it,st[y].size()-1);
		st[y].erase(x);
		return;
	}
	if (x==*st[y].rbegin())
	{
		set<int>::iterator it=st[y].find(x);it--;
		modify(1,1,n,*it,x-1,-1);
		update(1,1,n,*st[y].begin(),-1);
		st[y].erase(x);
		return;
	}
	update(1,1,n,*st[y].begin(),-1);
	st[y].erase(x);
}

inline void add(int x,int y)
{
	if (!st[y].size())
	{
		update(1,1,n,x,1);
		st[y].insert(x);
		return;
	}
	if (x<*st[y].begin())
	{
		set<int>::iterator it=st[y].begin();
		modify(1,1,n,x,(*it)-1,1);
		update(1,1,n,x,st[y].size()+1);
		update(1,1,n,*it,-st[y].size());
		st[y].insert(x);
		return;
	}
	if (x>*st[y].rbegin())
	{
		set<int>::reverse_iterator it=st[y].rbegin();
		modify(1,1,n,*it,x-1,1);
		update(1,1,n,*st[y].begin(),1);
		st[y].insert(x);
		return;
	}
	update(1,1,n,*st[y].begin(),1);
	st[y].insert(x);
}

int main()
{
	n=rd();q=rd();
	for (int i=1;i<=n;i++) num[i]=rd(),st[num[i]].insert(i);
	for (int i=1;i<=200000;i++) if (!st[i].empty())
	{
		update(1,1,n,*st[i].begin(),st[i].size());
		if ((*st[i].begin())!=(*st[i].rbegin())) modify(1,1,n,*st[i].begin(),*st[i].rbegin()-1,1);
	}
	print(n-smn[1]-sl[1]);
	while (q--)
	{
		int x=rd(),y=rd();
		del(x,num[x]);
		add(x,y);num[x]=y;
		print(n-smn[1]-sl[1]);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
struct dat{
	int mx,mn,ls,rs,ans;
};
dat t[N<<2];
int lzy[N<<2];
void pushup(dat &a,dat b,dat c){
	if(b.mn<c.mn){
		a.mn=b.mn;a.rs=max(b.rs,c.mx);
		a.ls=b.ls;a.ans=b.ans;
	}else if(b.mn>c.mn){
		a.mn=c.mn;a.ls=max(c.ls,b.mx);
		a.rs=c.rs;a.ans=c.ans;
	}else{
		a.mn=b.mn;a.rs=c.rs;
		a.ls=b.ls;a.ans=b.ans+c.ans+max(b.rs,c.ls);
	}
	a.mx=max(b.mx,c.mx);
}
inline void pushdown(int x){
	if(lzy[x]){
		lzy[x<<1]+=lzy[x],t[x<<1].mn+=lzy[x];
		lzy[x<<1|1]+=lzy[x],t[x<<1|1].mn+=lzy[x];
		lzy[x]=0;
	}
}
#define mid ((l+r)>>1)
inline void modify(int x,int l,int r,int ql,int qr,int sum){
	if(ql>qr)return ;
	if(ql<=l&&qr>=r){
		lzy[x] += sum;t[x].mn+=sum;
		return ;
	}
	pushdown(x);
	if(ql<=mid)modify(x<<1,l,mid,ql,qr,sum);
	if(qr>mid)modify(x<<1|1,mid+1,r,ql,qr,sum);
	pushup(t[x],t[x<<1],t[x<<1|1]);
}
inline void add(int x,int l,int r,int pos,int sum){
	if(l==r){
		t[x].ans=t[x].mx=sum;
		return ;
	}
	pushdown(x);
	if(pos<=mid)add(x<<1,l,mid,pos,sum);
	else add(x<<1|1,mid+1,r,pos,sum);
	pushup(t[x],t[x<<1],t[x<<1|1]);
}
#undef mid
set<int> s[N];
int n,q;
inline void del(int x){
	if(s[x].empty())return;
	modify(1,1,n,*s[x].begin(),*s[x].rbegin()-1,-1);
	add(1,1,n,*s[x].begin(),0);
}
inline void ins(int x){
	if(s[x].empty())return;
	modify(1,1,n,*s[x].begin(),*s[x].rbegin()-1,1);
	add(1,1,n,*s[x].begin(),s[x].size());
}
int a[N];
int main()
{
	cin >> n >> q;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		s[a[i]].insert(i);
	}
	for(int i=1;i<=200000;i++)ins(i);
	printf("%d\n",n-(t[1].ans+t[1].ls+t[1].rs));
	// cout << t[1].ans << " " << t[1].ls << " " << t[1].rs << endl;
	while(q--){
		int pos,x;scanf("%d%d",&pos,&x);
		del(a[pos]);
		s[a[pos]].erase(pos);
		ins(a[pos]);
		a[pos]=x;
		del(a[pos]);
		s[a[pos]].insert(pos);
		ins(a[pos]);
		printf("%d\n",n-(t[1].ans+t[1].ls+t[1].rs));
	}
}


#include <bits/stdc++.h>

using namespace std;

// copied from tourist's template

class node {
 public:
  node* l;
  node* r;
  node* p;
  bool rev;
  // declare extra variables:
  int tl;
  int tr;
  int tv;
  int ml;
  int mr;
  int mv;
  int sm;
  int id;

  void init(int _tl, int _tr, int _tv, int _id) {
    l = r = p = NULL;
    rev = false;
    // init extra variables:
    tl = _tl;
    tr = _tr;
    tv = _tv;
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    id = _id;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  // apply changes:
  void unsafe_apply() {
  }

  void push() {
    if (rev) {
      if (l != NULL) {
        l->unsafe_reverse();
      }
      if (r != NULL) {
        r->unsafe_reverse();
      }
      rev = 0;
    }
    // now push everything else:
  }

  void pull() {
    // now init from self:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    if (l != NULL) {
      l->p = this;
      // now pull from l:
      ml = min(ml, l->ml);
      mr = max(mr, l->mr);
      mv = max(mv, l->mv);
      sm += l->sm;
    }
    if (r != NULL) {
      r->p = this;
      // now pull from r:
      ml = min(ml, r->ml);
      mr = max(mr, r->mr);
      mv = max(mv, r->mv);
      sm += r->sm;
    }
  }
};

namespace splay_tree {
bool is_bst_root(node* v) {
  if (v == NULL) {
    return false;
  }
  return (v->p == NULL || (v->p->l != v && v->p->r != v));
}

void rotate(node* v) {
  node* u = v->p;
  assert(u != NULL);
  u->push();
  v->push();
  v->p = u->p;
  if (v->p != NULL) {
    if (v->p->l == u) {
      v->p->l = v;
    }
    if (v->p->r == u) {
      v->p->r = v;
    }
  }
  if (v == u->l) {
    u->l = v->r;
    v->r = u;
  } else {
    u->r = v->l;
    v->l = u;
  }
  u->pull();
  v->pull();
}

void splay(node* v) {
  if (v == NULL) {
    return;
  }
  while (!is_bst_root(v)) {
    node* u = v->p;
    if (!is_bst_root(u)) {
      if ((u->l == v) ^ (u->p->l == u)) {
        rotate(v);
      } else {
        rotate(u);
      }
    }
    rotate(v);
  }
}

pair<node*, int> find(node* v, const function<int(node*)> &go_to) {
  // go_to returns: 0 -- found; -1 -- go left; 1 -- go right
  // find returns the last vertex on the descent and its go_to
  if (v == NULL) {
    return {NULL, 0};
  }
  splay(v);
  int dir;
  while (true) {
    v->push();
    dir = go_to(v);
    if (dir == 0) {
      break;
    }
    node* u = (dir == -1 ? v->l : v->r);
    if (u == NULL) {
      break;
    }
    v = u;
  }
  splay(v);
  return {v, dir};
}

node* get_leftmost(node* v) {
  return find(v, [&](node*) {
    return -1;
  }).first;
}

node* get_rightmost(node* v) {
  return find(v, [&](node*) {
    return 1;
  }).first;
}

node* get_bst_root(node* v) {
  splay(v);
  return v;
}

pair<node*, node*> split(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return {NULL, NULL};
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  v = p.first;
  v->push();
  if (p.second == -1) {
    node* u = v->l;
    if (u == NULL) {
      return {NULL, v};
    }
    v->l = NULL;
    u->p = v->p;
    u = get_rightmost(u);
    v->p = u;
    v->pull();
    return {u, v};
  } else {
    node* u = v->r;
    if (u == NULL) {
      return {v, NULL};
    }
    v->r = NULL;
    v->pull();
    return {v, u};
  }
}

node* merge(node* v, node* u) {
  if (v == NULL) {
    return u;
  }
  if (u == NULL) {
    return v;
  }
  v = get_rightmost(v);
  assert(v->r == NULL);
  splay(u);
  v->push();
  v->r = u;
  v->pull();
  return v;
}

node* add(node* r, node* v, const function<bool(node*)> &go_left) {
  pair<node*, node*> p = split(r, go_left);
  return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
  splay(v);
  v->push();
  node* x = v->l;
  node* y = v->r;
  v->l = v->r = NULL;
  node* z = merge(x, y);
  if (z != NULL) {
    z->p = v->p;
  }
  v->p = NULL;
  v->push();
  v->pull(); // now v might be reusable...
  return z;
}

node* next(node* v) {
  splay(v);
  v->push();
  if (v->r == NULL) {
    return NULL;
  }
  v = v->r;
  while (v->l != NULL) {
    v->push();
    v = v->l;
  }
  splay(v);
  return v;
}

node* prev(node* v) {
  splay(v);
  v->push();
  if (v->l == NULL) {
    return NULL;
  }
  v = v->l;
  while (v->r != NULL) {
    v->push();
    v = v->r;
  }
  splay(v);
  return v;
}

template<typename... T>
void apply(node* v, T... args) {
  splay(v);
  v->unsafe_apply(args...);
}

void reverse(node* v) {
  splay(v);
  v->unsafe_reverse();
}
}

using namespace splay_tree;

const int N = 1234567;
const int M = 2234567;

int n, m, q, ptr, a[N], l[N], r[N], tl[N], tr[N], tv[N], cur[N];
node* root = NULL;
vector<int> ev[N];
node* erased[N];
set<int> st[N];
stack<int> pl;
node pool[M];

node* new_node(int tl, int tr, int tv) {
  node* v;
  int id;
  if (pl.empty()) {
    v = &pool[ptr];
    id = ptr++;
  } else {
    id = pl.top();
    pl.pop();
    v = &pool[id];
  }
  v->init(tl, tr, tv, id);
  return v;
}

void erase_node(node* v) {
  pl.push(v->id);
}

void add(int x, int l, int r, int ll, int rr, int i) {
  if (ll <= l && r <= rr) {
    ev[x].push_back(i);
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    if (ll <= y) {
      add(x + 1, l, y, ll, rr, i);
    }
    if (rr > y) {
      add(z, y + 1, r, ll, rr, i);
    }
  }
}

void solve(int x, int l, int r) {
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    node* v = new_node(tl[i], tr[i], tv[i]);
    if (middle != NULL) {
      v->tl = min(v->tl, middle->ml);
      v->tr = max(v->tr, middle->mr);
      v->tv = max(v->tv, middle->mv);
      v->pull();
    }
    erased[i] = middle;
    root = merge(left, merge(v, right));
  }
  reverse(ev[x].begin(), ev[x].end());
  if (l == r) {
    cout << (n - root->sm) << "\n";
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    solve(x + 1, l, y);
    solve(z, y + 1, r);
  }
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    root = merge(left, merge(erased[i], right));
    erase_node(middle);
  }
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    st[a[i]].insert(i);
  }
  for (int i = 0; i < N; ++i) {
    if (!st[i].empty()) {
      cur[i] = m;
      tl[m] = *st[i].begin();
      tr[m] = *st[i].rbegin();
      tv[m] = st[i].size();
      l[m] = 0;
      r[m] = q;
      m++;
    } else {
      cur[i] = -1;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int p;
    cin >> p;
    --p;
    st[a[p]].erase(p);
    r[cur[a[p]]] = i - 1;
    if (!st[a[p]].empty()) {
      cur[a[p]] = m;
      tl[m] = *st[a[p]].begin();
      tr[m] = *st[a[p]].rbegin();
      tv[m] = st[a[p]].size();
      l[m] = i;
      r[m] = q;
      m++;
    } else {
      cur[a[p]] = -1;
    }
    cin >> a[p];
    st[a[p]].insert(p);
    if (cur[a[p]] != -1) {
      r[cur[a[p]]] = i - 1;
    }
    cur[a[p]] = m;
    tl[m] = *st[a[p]].begin();
    tr[m] = *st[a[p]].rbegin();
    tv[m] = st[a[p]].size();
    l[m] = i;
    r[m] = q;
    m++;
  }
  for (int i = 0; i < m; ++i) {
    if (l[i] <= r[i]) {
      add(0, 0, q, l[i], r[i], i);
    }
  }
  solve(0, 0, q);
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

// copied from tourist's template

class node {
 public:
  node* l;
  node* r;
  node* p;
  bool rev;
  int sz;
  // declare extra variables:
  int tl;
  int tr;
  int tv;
  int ml;
  int mr;
  int mv;
  int sm;
  int id;

  void init(int _tl, int _tr, int _tv, int _id) {
    l = r = p = NULL;
    rev = false;
    sz = 1;
    // init extra variables:
    tl = _tl;
    tr = _tr;
    tv = _tv;
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    id = _id;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  // apply changes:
  void unsafe_apply() {
  }

  void push() {
    if (rev) {
      if (l != NULL) {
        l->unsafe_reverse();
      }
      if (r != NULL) {
        r->unsafe_reverse();
      }
      rev = 0;
    }
    // now push everything else:
  }

  void pull() {
    sz = 1;
    // now init from self:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    if (l != NULL) {
      l->p = this;
      sz += l->sz;
      // now pull from l:
      ml = min(ml, l->ml);
      mr = max(mr, l->mr);
      mv = max(mv, l->mv);
      sm += l->sm;
    }
    if (r != NULL) {
      r->p = this;
      sz += r->sz;
      // now pull from r:
      ml = min(ml, r->ml);
      mr = max(mr, r->mr);
      mv = max(mv, r->mv);
      sm += r->sm;
    }
  }
};

namespace splay_tree {
bool is_bst_root(node* v) {
  if (v == NULL) {
    return false;
  }
  return (v->p == NULL || (v->p->l != v && v->p->r != v));
}

void rotate(node* v) {
  node* u = v->p;
  assert(u != NULL);
  u->push();
  v->push();
  v->p = u->p;
  if (v->p != NULL) {
    if (v->p->l == u) {
      v->p->l = v;
    }
    if (v->p->r == u) {
      v->p->r = v;
    }
  }
  if (v == u->l) {
    u->l = v->r;
    v->r = u;
  } else {
    u->r = v->l;
    v->l = u;
  }
  u->pull();
  v->pull();
}

void splay(node* v) {
  if (v == NULL) {
    return;
  }
  while (!is_bst_root(v)) {
    node* u = v->p;
    if (!is_bst_root(u)) {
      if ((u->l == v) ^ (u->p->l == u)) {
        rotate(v);
      } else {
        rotate(u);
      }
    }
    rotate(v);
  }
}

pair<node*, int> find(node* v, const function<int(node*)> &go_to) {
  // go_to returns: 0 -- found; -1 -- go left; 1 -- go right
  // find returns the last vertex on the descent and its go_to
  if (v == NULL) {
    return {NULL, 0};
  }
  splay(v);
  int dir;
  while (true) {
    v->push();
    dir = go_to(v);
    if (dir == 0) {
      break;
    }
    node* u = (dir == -1 ? v->l : v->r);
    if (u == NULL) {
      break;
    }
    v = u;
  }
  splay(v);
  return {v, dir};
}

node* get_leftmost(node* v) {
  return find(v, [&](node*) {
    return -1;
  }).first;
}

node* get_rightmost(node* v) {
  return find(v, [&](node*) {
    return 1;
  }).first;
}

node* get_kth(node* v, int k) { // 0-indexed
  pair<node*, int> p = find(v, [&](node * u) {
    if (u->l != NULL) {
      if (u->l->sz > k) {
        return -1;
      }
      k -= u->l->sz;
    }
    if (k == 0) {
      return 0;
    }
    k--;
    return 1;
  });
  return (p.second == 0 ? p.first : NULL);
}

int get_position(node* v) { // 0-indexed
  splay(v);
  return (v->l != NULL ? v->l->sz : 0);
}

node* get_bst_root(node* v) {
  splay(v);
  return v;
}

pair<node*, node*> split(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return {NULL, NULL};
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  v = p.first;
  v->push();
  if (p.second == -1) {
    node* u = v->l;
    if (u == NULL) {
      return {NULL, v};
    }
    v->l = NULL;
    u->p = v->p;
    u = get_rightmost(u);
    v->p = u;
    v->pull();
    return {u, v};
  } else {
    node* u = v->r;
    if (u == NULL) {
      return {v, NULL};
    }
    v->r = NULL;
    v->pull();
    return {v, u};
  }
}

pair<node*, node*> split_leftmost_k(node* v, int k) {
  return split(v, [&](node * u) {
    int left_and_me = (u->l != NULL ? u->l->sz : 0) + 1;
    if (k >= left_and_me) {
      k -= left_and_me;
      return false;
    }
    return true;
  });
}

node* merge(node* v, node* u) {
  if (v == NULL) {
    return u;
  }
  if (u == NULL) {
    return v;
  }
  v = get_rightmost(v);
  assert(v->r == NULL);
  splay(u);
  v->push();
  v->r = u;
  v->pull();
  return v;
}

int count_left(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return 0;
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  node* u = p.first;
  return (u->l != NULL ? u->l->sz : 0) + (p.second == 1);
}

node* add(node* r, node* v, const function<bool(node*)> &go_left) {
  pair<node*, node*> p = split(r, go_left);
  return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
  splay(v);
  v->push();
  node* x = v->l;
  node* y = v->r;
  v->l = v->r = NULL;
  node* z = merge(x, y);
  if (z != NULL) {
    z->p = v->p;
  }
  v->p = NULL;
  v->push();
  v->pull(); // now v might be reusable...
  return z;
}

node* next(node* v) {
  splay(v);
  v->push();
  if (v->r == NULL) {
    return NULL;
  }
  v = v->r;
  while (v->l != NULL) {
    v->push();
    v = v->l;
  }
  splay(v);
  return v;
}

node* prev(node* v) {
  splay(v);
  v->push();
  if (v->l == NULL) {
    return NULL;
  }
  v = v->l;
  while (v->r != NULL) {
    v->push();
    v = v->r;
  }
  splay(v);
  return v;
}

int get_size(node* v) {
  splay(v);
  return (v != NULL ? v->sz : 0);
}

template<typename... T>
void apply(node* v, T... args) {
  splay(v);
  v->unsafe_apply(args...);
}

void reverse(node* v) {
  splay(v);
  v->unsafe_reverse();
}
}

using namespace splay_tree;

const int N = 1234567;
const int M = 5234567;

int n, m, q, ptr, a[N], l[N], r[N], tl[N], tr[N], tv[N], cur[N];
node* root = NULL;
vector<int> ev[N];
node* erased[N];
set<int> st[N];
stack<int> pl;
node pool[M];

node* new_node(int tl, int tr, int tv) {
  node* v;
  int id;
  if (pl.empty()) {
    v = &pool[ptr];
    id = ptr++;
  } else {
    id = pl.top();
    pl.pop();
    v = &pool[id];
  }
  v->init(tl, tr, tv, id);
  return v;
}

void erase_node(node* v) {
  pl.push(v->id);
}

void add(int x, int l, int r, int ll, int rr, int i) {
  if (ll <= l && r <= rr) {
    ev[x].push_back(i);
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    if (ll <= y) {
      add(x + 1, l, y, ll, rr, i);
    }
    if (rr > y) {
      add(z, y + 1, r, ll, rr, i);
    }
  }
}

void solve(int x, int l, int r) {
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    node* v = new_node(tl[i], tr[i], tv[i]);
    if (middle != NULL) {
      v->tl = min(v->tl, middle->ml);
      v->tr = max(v->tr, middle->mr);
      v->tv = max(v->tv, middle->mv);
      v->pull();
    }
    erased[i] = middle;
    root = merge(left, merge(v, right));
  }
  reverse(ev[x].begin(), ev[x].end());
  if (l == r) {
    cout << (n - root->sm) << "\n";
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    solve(x + 1, l, y);
    solve(z, y + 1, r);
  }
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    root = merge(left, merge(erased[i], right));
    erase_node(middle);
  }
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    st[a[i]].insert(i);
  }
  for (int i = 0; i < N; ++i) {
    if (!st[i].empty()) {
      cur[i] = m;
      tl[m] = *st[i].begin();
      tr[m] = *st[i].rbegin();
      tv[m] = st[i].size();
      l[m] = 0;
      r[m] = q;
      m++;
    } else {
      cur[i] = -1;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int p;
    cin >> p;
    --p;
    st[a[p]].erase(p);
    r[cur[a[p]]] = i - 1;
    if (!st[a[p]].empty()) {
      cur[a[p]] = m;
      tl[m] = *st[a[p]].begin();
      tr[m] = *st[a[p]].rbegin();
      tv[m] = st[a[p]].size();
      l[m] = i;
      r[m] = q;
      m++;
    } else {
      cur[a[p]] = -1;
    }
    cin >> a[p];
    st[a[p]].insert(p);
    if (cur[a[p]] != -1) {
      r[cur[a[p]]] = i - 1;
    }
    cur[a[p]] = m;
    tl[m] = *st[a[p]].begin();
    tr[m] = *st[a[p]].rbegin();
    tv[m] = st[a[p]].size();
    l[m] = i;
    r[m] = q;
    m++;
  }
  for (int i = 0; i < m; ++i) {
    if (l[i] <= r[i]) {
      add(0, 0, q, l[i], r[i], i);
    }
  }
  solve(0, 0, q);
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

// copied from tourist's template

class node {
 public:
  node* l;
  node* r;
  node* p;
  bool rev;
  int sz;
  // declare extra variables:
  int tl;
  int tr;
  int tv;
  int ml;
  int mr;
  int mv;
  int sm;

  node(int tl, int tr, int tv) : tl(tl), tr(tr), tv(tv) {
    l = r = p = NULL;
    rev = false;
    sz = 1;
    // init extra variables:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  // apply changes:
  void unsafe_apply() {
  }

  void push() {
    if (rev) {
      if (l != NULL) {
        l->unsafe_reverse();
      }
      if (r != NULL) {
        r->unsafe_reverse();
      }
      rev = 0;
    }
    // now push everything else:
  }

  void pull() {
    sz = 1;
    // now init from self:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    if (l != NULL) {
      l->p = this;
      sz += l->sz;
      // now pull from l:
      ml = min(ml, l->ml);
      mr = max(mr, l->mr);
      mv = max(mv, l->mv);
      sm += l->sm;
    }
    if (r != NULL) {
      r->p = this;
      sz += r->sz;
      // now pull from r:
      ml = min(ml, r->ml);
      mr = max(mr, r->mr);
      mv = max(mv, r->mv);
      sm += r->sm;
    }
  }
};

namespace splay_tree {
bool is_bst_root(node* v) {
  if (v == NULL) {
    return false;
  }
  return (v->p == NULL || (v->p->l != v && v->p->r != v));
}

void rotate(node* v) {
  node* u = v->p;
  assert(u != NULL);
  u->push();
  v->push();
  v->p = u->p;
  if (v->p != NULL) {
    if (v->p->l == u) {
      v->p->l = v;
    }
    if (v->p->r == u) {
      v->p->r = v;
    }
  }
  if (v == u->l) {
    u->l = v->r;
    v->r = u;
  } else {
    u->r = v->l;
    v->l = u;
  }
  u->pull();
  v->pull();
}

void splay(node* v) {
  if (v == NULL) {
    return;
  }
  while (!is_bst_root(v)) {
    node* u = v->p;
    if (!is_bst_root(u)) {
      if ((u->l == v) ^ (u->p->l == u)) {
        rotate(v);
      } else {
        rotate(u);
      }
    }
    rotate(v);
  }
}

pair<node*, int> find(node* v, const function<int(node*)> &go_to) {
  // go_to returns: 0 -- found; -1 -- go left; 1 -- go right
  // find returns the last vertex on the descent and its go_to
  if (v == NULL) {
    return {NULL, 0};
  }
  splay(v);
  int dir;
  while (true) {
    v->push();
    dir = go_to(v);
    if (dir == 0) {
      break;
    }
    node* u = (dir == -1 ? v->l : v->r);
    if (u == NULL) {
      break;
    }
    v = u;
  }
  splay(v);
  return {v, dir};
}

node* get_leftmost(node* v) {
  return find(v, [&](node*) {
    return -1;
  }).first;
}

node* get_rightmost(node* v) {
  return find(v, [&](node*) {
    return 1;
  }).first;
}

node* get_kth(node* v, int k) { // 0-indexed
  pair<node*, int> p = find(v, [&](node * u) {
    if (u->l != NULL) {
      if (u->l->sz > k) {
        return -1;
      }
      k -= u->l->sz;
    }
    if (k == 0) {
      return 0;
    }
    k--;
    return 1;
  });
  return (p.second == 0 ? p.first : NULL);
}

int get_position(node* v) { // 0-indexed
  splay(v);
  return (v->l != NULL ? v->l->sz : 0);
}

node* get_bst_root(node* v) {
  splay(v);
  return v;
}

pair<node*, node*> split(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return {NULL, NULL};
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  v = p.first;
  v->push();
  if (p.second == -1) {
    node* u = v->l;
    if (u == NULL) {
      return {NULL, v};
    }
    v->l = NULL;
    u->p = v->p;
    u = get_rightmost(u);
    v->p = u;
    v->pull();
    return {u, v};
  } else {
    node* u = v->r;
    if (u == NULL) {
      return {v, NULL};
    }
    v->r = NULL;
    v->pull();
    return {v, u};
  }
}

pair<node*, node*> split_leftmost_k(node* v, int k) {
  return split(v, [&](node * u) {
    int left_and_me = (u->l != NULL ? u->l->sz : 0) + 1;
    if (k >= left_and_me) {
      k -= left_and_me;
      return false;
    }
    return true;
  });
}

node* merge(node* v, node* u) {
  if (v == NULL) {
    return u;
  }
  if (u == NULL) {
    return v;
  }
  v = get_rightmost(v);
  assert(v->r == NULL);
  splay(u);
  v->push();
  v->r = u;
  v->pull();
  return v;
}

int count_left(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return 0;
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  node* u = p.first;
  return (u->l != NULL ? u->l->sz : 0) + (p.second == 1);
}

node* add(node* r, node* v, const function<bool(node*)> &go_left) {
  pair<node*, node*> p = split(r, go_left);
  return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
  splay(v);
  v->push();
  node* x = v->l;
  node* y = v->r;
  v->l = v->r = NULL;
  node* z = merge(x, y);
  if (z != NULL) {
    z->p = v->p;
  }
  v->p = NULL;
  v->push();
  v->pull(); // now v might be reusable...
  return z;
}

node* next(node* v) {
  splay(v);
  v->push();
  if (v->r == NULL) {
    return NULL;
  }
  v = v->r;
  while (v->l != NULL) {
    v->push();
    v = v->l;
  }
  splay(v);
  return v;
}

node* prev(node* v) {
  splay(v);
  v->push();
  if (v->l == NULL) {
    return NULL;
  }
  v = v->l;
  while (v->r != NULL) {
    v->push();
    v = v->r;
  }
  splay(v);
  return v;
}

int get_size(node* v) {
  splay(v);
  return (v != NULL ? v->sz : 0);
}

template<typename... T>
void apply(node* v, T... args) {
  splay(v);
  v->unsafe_apply(args...);
}

void reverse(node* v) {
  splay(v);
  v->unsafe_reverse();
}
}

using namespace splay_tree;

const int N = 1234567;

int n, m, q, a[N], l[N], r[N], tl[N], tr[N], tv[N], cur[N];
node* root = NULL;
vector<int> ev[N];
node* erased[N];
set<int> st[N];

void add(int x, int l, int r, int ll, int rr, int i) {
  if (ll <= l && r <= rr) {
    ev[x].push_back(i);
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    if (ll <= y) {
      add(x + 1, l, y, ll, rr, i);
    }
    if (rr > y) {
      add(z, y + 1, r, ll, rr, i);
    }
  }
}

void solve(int x, int l, int r) {
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    node* v = new node(tl[i], tr[i], tv[i]);
    if (middle != NULL) {
      v->tl = min(v->tl, middle->ml);
      v->tr = max(v->tr, middle->mr);
      v->tv = max(v->tv, middle->mv);
      v->pull();
    }
    erased[i] = middle;
    root = merge(left, merge(v, right));
  }
  reverse(ev[x].begin(), ev[x].end());
  if (l == r) {
    cout << (n - root->sm) << "\n";
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    solve(x + 1, l, y);
    solve(z, y + 1, r);
  }
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    root = merge(left, merge(erased[i], right));
  }
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    st[a[i]].insert(i);
  }
  for (int i = 0; i < N; ++i) {
    if (!st[i].empty()) {
      cur[i] = m;
      tl[m] = *st[i].begin();
      tr[m] = *st[i].rbegin();
      tv[m] = st[i].size();
      l[m] = 0;
      r[m] = q;
      m++;
    } else {
      cur[i] = -1;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int p;
    cin >> p;
    --p;
    st[a[p]].erase(p);
    r[cur[a[p]]] = i - 1;
    if (!st[a[p]].empty()) {
      cur[a[p]] = m;
      tl[m] = *st[a[p]].begin();
      tr[m] = *st[a[p]].rbegin();
      tv[m] = st[a[p]].size();
      l[m] = i;
      r[m] = q;
      m++;
    } else {
      cur[a[p]] = -1;
    }
    cin >> a[p];
    st[a[p]].insert(p);
    if (cur[a[p]] != -1) {
      r[cur[a[p]]] = i - 1;
    }
    cur[a[p]] = m;
    tl[m] = *st[a[p]].begin();
    tr[m] = *st[a[p]].rbegin();
    tv[m] = st[a[p]].size();
    l[m] = i;
    r[m] = q;
    m++;
  }
  for (int i = 0; i < m; ++i) {
    add(0, 0, q, l[i], r[i], i);
  }
  solve(0, 0, q);
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

// copied from tourist's template

class node {
 public:
  node* l;
  node* r;
  node* p;
  bool rev;
  int sz;
  // declare extra variables:
  int tl;
  int tr;
  int tv;
  int ml;
  int mr;
  int mv;
  int sm;

  node(int tl, int tr, int tv) : tl(tl), tr(tr), tv(tv) {
    l = r = p = NULL;
    rev = false;
    sz = 1;
    // init extra variables:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  // apply changes:
  void unsafe_apply() {
  }

  void push() {
    if (rev) {
      if (l != NULL) {
        l->unsafe_reverse();
      }
      if (r != NULL) {
        r->unsafe_reverse();
      }
      rev = 0;
    }
    // now push everything else:
  }

  void pull() {
    sz = 1;
    // now init from self:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    if (l != NULL) {
      l->p = this;
      sz += l->sz;
      // now pull from l:
      ml = min(ml, l->ml);
      mr = max(mr, l->mr);
      mv = max(mv, l->mv);
      sm += l->sm;
    }
    if (r != NULL) {
      r->p = this;
      sz += r->sz;
      // now pull from r:
      ml = min(ml, r->ml);
      mr = max(mr, r->mr);
      mv = max(mv, r->mv);
      sm += r->sm;
    }
  }
};

namespace splay_tree {
bool is_bst_root(node* v) {
  if (v == NULL) {
    return false;
  }
  return (v->p == NULL || (v->p->l != v && v->p->r != v));
}

void rotate(node* v) {
  node* u = v->p;
  assert(u != NULL);
  u->push();
  v->push();
  v->p = u->p;
  if (v->p != NULL) {
    if (v->p->l == u) {
      v->p->l = v;
    }
    if (v->p->r == u) {
      v->p->r = v;
    }
  }
  if (v == u->l) {
    u->l = v->r;
    v->r = u;
  } else {
    u->r = v->l;
    v->l = u;
  }
  u->pull();
  v->pull();
}

void splay(node* v) {
  if (v == NULL) {
    return;
  }
  while (!is_bst_root(v)) {
    node* u = v->p;
    if (!is_bst_root(u)) {
      if ((u->l == v) ^ (u->p->l == u)) {
        rotate(v);
      } else {
        rotate(u);
      }
    }
    rotate(v);
  }
}

pair<node*, int> find(node* v, const function<int(node*)> &go_to) {
  // go_to returns: 0 -- found; -1 -- go left; 1 -- go right
  // find returns the last vertex on the descent and its go_to
  if (v == NULL) {
    return {NULL, 0};
  }
  splay(v);
  int dir;
  while (true) {
    v->push();
    dir = go_to(v);
    if (dir == 0) {
      break;
    }
    node* u = (dir == -1 ? v->l : v->r);
    if (u == NULL) {
      break;
    }
    v = u;
  }
  splay(v);
  return {v, dir};
}

node* get_leftmost(node* v) {
  return find(v, [&](node*) {
    return -1;
  }).first;
}

node* get_rightmost(node* v) {
  return find(v, [&](node*) {
    return 1;
  }).first;
}

node* get_kth(node* v, int k) { // 0-indexed
  pair<node*, int> p = find(v, [&](node * u) {
    if (u->l != NULL) {
      if (u->l->sz > k) {
        return -1;
      }
      k -= u->l->sz;
    }
    if (k == 0) {
      return 0;
    }
    k--;
    return 1;
  });
  return (p.second == 0 ? p.first : NULL);
}

int get_position(node* v) { // 0-indexed
  splay(v);
  return (v->l != NULL ? v->l->sz : 0);
}

node* get_bst_root(node* v) {
  splay(v);
  return v;
}

pair<node*, node*> split(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return {NULL, NULL};
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  v = p.first;
  v->push();
  if (p.second == -1) {
    node* u = v->l;
    if (u == NULL) {
      return {NULL, v};
    }
    v->l = NULL;
    u->p = v->p;
    u = get_rightmost(u);
    v->p = u;
    v->pull();
    return {u, v};
  } else {
    node* u = v->r;
    if (u == NULL) {
      return {v, NULL};
    }
    v->r = NULL;
    v->pull();
    return {v, u};
  }
}

pair<node*, node*> split_leftmost_k(node* v, int k) {
  return split(v, [&](node * u) {
    int left_and_me = (u->l != NULL ? u->l->sz : 0) + 1;
    if (k >= left_and_me) {
      k -= left_and_me;
      return false;
    }
    return true;
  });
}

node* merge(node* v, node* u) {
  if (v == NULL) {
    return u;
  }
  if (u == NULL) {
    return v;
  }
  v = get_rightmost(v);
  assert(v->r == NULL);
  splay(u);
  v->push();
  v->r = u;
  v->pull();
  return v;
}

int count_left(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return 0;
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  node* u = p.first;
  return (u->l != NULL ? u->l->sz : 0) + (p.second == 1);
}

node* add(node* r, node* v, const function<bool(node*)> &go_left) {
  pair<node*, node*> p = split(r, go_left);
  return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
  splay(v);
  v->push();
  node* x = v->l;
  node* y = v->r;
  v->l = v->r = NULL;
  node* z = merge(x, y);
  if (z != NULL) {
    z->p = v->p;
  }
  v->p = NULL;
  v->push();
  v->pull(); // now v might be reusable...
  return z;
}

node* next(node* v) {
  splay(v);
  v->push();
  if (v->r == NULL) {
    return NULL;
  }
  v = v->r;
  while (v->l != NULL) {
    v->push();
    v = v->l;
  }
  splay(v);
  return v;
}

node* prev(node* v) {
  splay(v);
  v->push();
  if (v->l == NULL) {
    return NULL;
  }
  v = v->l;
  while (v->r != NULL) {
    v->push();
    v = v->r;
  }
  splay(v);
  return v;
}

int get_size(node* v) {
  splay(v);
  return (v != NULL ? v->sz : 0);
}

template<typename... T>
void apply(node* v, T... args) {
  splay(v);
  v->unsafe_apply(args...);
}

void reverse(node* v) {
  splay(v);
  v->unsafe_reverse();
}
}

using namespace splay_tree;

const int N = 1234567;

int n, m, q, a[N], l[N], r[N], tl[N], tr[N], tv[N], cur[N];
node* root = NULL;
vector<int> ev[N];
node* erased[N];
set<int> st[N];

void add(int x, int l, int r, int ll, int rr, int i) {
  if (ll <= l && r <= rr) {
    ev[x].push_back(i);
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    if (ll <= y) {
      add(x + 1, l, y, ll, rr, i);
    }
    if (rr > y) {
      add(z, y + 1, r, ll, rr, i);
    }
  }
}

void solve(int x, int l, int r) {
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    node* v = new node(tl[i], tr[i], tv[i]);
    if (middle != NULL) {
      v->tl = min(v->tl, middle->ml);
      v->tr = max(v->tr, middle->mr);
      v->tv = max(v->tv, middle->mv);
      v->pull();
    }
    erased[i] = middle;
    root = merge(left, merge(v, right));
  }
  reverse(ev[x].begin(), ev[x].end());
  if (l == r) {
    cout << (n - root->sm) << "\n";
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    solve(x + 1, l, y);
    solve(z, y + 1, r);
  }
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    root = merge(left, merge(erased[i], right));
    if (middle != NULL) {
      delete middle;
    }
  }
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    st[a[i]].insert(i);
  }
  for (int i = 0; i < N; ++i) {
    if (!st[i].empty()) {
      cur[i] = m;
      tl[m] = *st[i].begin();
      tr[m] = *st[i].rbegin();
      tv[m] = st[i].size();
      l[m] = 0;
      r[m] = q;
      m++;
    } else {
      cur[i] = -1;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int p;
    cin >> p;
    --p;
    st[a[p]].erase(p);
    r[cur[a[p]]] = i - 1;
    if (!st[a[p]].empty()) {
      cur[a[p]] = m;
      tl[m] = *st[a[p]].begin();
      tr[m] = *st[a[p]].rbegin();
      tv[m] = st[a[p]].size();
      l[m] = i;
      r[m] = q;
      m++;
    } else {
      cur[a[p]] = -1;
    }
    cin >> a[p];
    st[a[p]].insert(p);
    if (cur[a[p]] != -1) {
      r[cur[a[p]]] = i - 1;
    }
    cur[a[p]] = m;
    tl[m] = *st[a[p]].begin();
    tr[m] = *st[a[p]].rbegin();
    tv[m] = st[a[p]].size();
    l[m] = i;
    r[m] = q;
    m++;
  }
  for (int i = 0; i < m; ++i) {
    add(0, 0, q, l[i], r[i], i);
  }
  solve(0, 0, q);
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

// copied from tourist's template

class node {
 public:
  node* l;
  node* r;
  node* p;
  bool rev;
  int sz;
  // declare extra variables:
  int tl;
  int tr;
  int tv;
  int ml;
  int mr;
  int mv;
  int sm;

  node(int tl, int tr, int tv) : tl(tl), tr(tr), tv(tv) {
    l = r = p = NULL;
    rev = false;
    sz = 1;
    // init extra variables:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
  }

  void unsafe_reverse() {
    rev ^= 1;
    swap(l, r);
    pull();
  }

  // apply changes:
  void unsafe_apply() {
  }

  void push() {
    if (rev) {
      if (l != NULL) {
        l->unsafe_reverse();
      }
      if (r != NULL) {
        r->unsafe_reverse();
      }
      rev = 0;
    }
    // now push everything else:
  }

  void pull() {
    sz = 1;
    // now init from self:
    ml = tl;
    mr = tr;
    mv = tv;
    sm = tv;
    if (l != NULL) {
      l->p = this;
      sz += l->sz;
      // now pull from l:
      ml = min(ml, l->ml);
      mr = max(mr, l->mr);
      mv = max(mv, l->mv);
      sm += l->sm;
    }
    if (r != NULL) {
      r->p = this;
      sz += r->sz;
      // now pull from r:
      ml = min(ml, r->ml);
      mr = max(mr, r->mr);
      mv = max(mv, r->mv);
      sm += r->sm;
    }
  }
};

namespace splay_tree {
bool is_bst_root(node* v) {
  if (v == NULL) {
    return false;
  }
  return (v->p == NULL || (v->p->l != v && v->p->r != v));
}

void rotate(node* v) {
  node* u = v->p;
  assert(u != NULL);
  u->push();
  v->push();
  v->p = u->p;
  if (v->p != NULL) {
    if (v->p->l == u) {
      v->p->l = v;
    }
    if (v->p->r == u) {
      v->p->r = v;
    }
  }
  if (v == u->l) {
    u->l = v->r;
    v->r = u;
  } else {
    u->r = v->l;
    v->l = u;
  }
  u->pull();
  v->pull();
}

void splay(node* v) {
  if (v == NULL) {
    return;
  }
  while (!is_bst_root(v)) {
    node* u = v->p;
    if (!is_bst_root(u)) {
      if ((u->l == v) ^ (u->p->l == u)) {
        rotate(v);
      } else {
        rotate(u);
      }
    }
    rotate(v);
  }
}

pair<node*, int> find(node* v, const function<int(node*)> &go_to) {
  // go_to returns: 0 -- found; -1 -- go left; 1 -- go right
  // find returns the last vertex on the descent and its go_to
  if (v == NULL) {
    return {NULL, 0};
  }
  splay(v);
  int dir;
  while (true) {
    v->push();
    dir = go_to(v);
    if (dir == 0) {
      break;
    }
    node* u = (dir == -1 ? v->l : v->r);
    if (u == NULL) {
      break;
    }
    v = u;
  }
  splay(v);
  return {v, dir};
}

node* get_leftmost(node* v) {
  return find(v, [&](node*) {
    return -1;
  }).first;
}

node* get_rightmost(node* v) {
  return find(v, [&](node*) {
    return 1;
  }).first;
}

node* get_kth(node* v, int k) { // 0-indexed
  pair<node*, int> p = find(v, [&](node * u) {
    if (u->l != NULL) {
      if (u->l->sz > k) {
        return -1;
      }
      k -= u->l->sz;
    }
    if (k == 0) {
      return 0;
    }
    k--;
    return 1;
  });
  return (p.second == 0 ? p.first : NULL);
}

int get_position(node* v) { // 0-indexed
  splay(v);
  return (v->l != NULL ? v->l->sz : 0);
}

node* get_bst_root(node* v) {
  splay(v);
  return v;
}

pair<node*, node*> split(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return {NULL, NULL};
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  v = p.first;
  v->push();
  if (p.second == -1) {
    node* u = v->l;
    if (u == NULL) {
      return {NULL, v};
    }
    v->l = NULL;
    u->p = v->p;
    u = get_rightmost(u);
    v->p = u;
    v->pull();
    return {u, v};
  } else {
    node* u = v->r;
    if (u == NULL) {
      return {v, NULL};
    }
    v->r = NULL;
    v->pull();
    return {v, u};
  }
}

pair<node*, node*> split_leftmost_k(node* v, int k) {
  return split(v, [&](node * u) {
    int left_and_me = (u->l != NULL ? u->l->sz : 0) + 1;
    if (k >= left_and_me) {
      k -= left_and_me;
      return false;
    }
    return true;
  });
}

node* merge(node* v, node* u) {
  if (v == NULL) {
    return u;
  }
  if (u == NULL) {
    return v;
  }
  v = get_rightmost(v);
  assert(v->r == NULL);
  splay(u);
  v->push();
  v->r = u;
  v->pull();
  return v;
}

int count_left(node* v, const function<bool(node*)> &is_right) {
  if (v == NULL) {
    return 0;
  }
  pair<node*, int> p = find(v, [&](node * u) {
    return is_right(u) ? -1 : 1;
  });
  node* u = p.first;
  return (u->l != NULL ? u->l->sz : 0) + (p.second == 1);
}

node* add(node* r, node* v, const function<bool(node*)> &go_left) {
  pair<node*, node*> p = split(r, go_left);
  return merge(p.first, merge(v, p.second));
}

node* remove(node* v) { // returns the new root
  splay(v);
  v->push();
  node* x = v->l;
  node* y = v->r;
  v->l = v->r = NULL;
  node* z = merge(x, y);
  if (z != NULL) {
    z->p = v->p;
  }
  v->p = NULL;
  v->push();
  v->pull(); // now v might be reusable...
  return z;
}

node* next(node* v) {
  splay(v);
  v->push();
  if (v->r == NULL) {
    return NULL;
  }
  v = v->r;
  while (v->l != NULL) {
    v->push();
    v = v->l;
  }
  splay(v);
  return v;
}

node* prev(node* v) {
  splay(v);
  v->push();
  if (v->l == NULL) {
    return NULL;
  }
  v = v->l;
  while (v->r != NULL) {
    v->push();
    v = v->r;
  }
  splay(v);
  return v;
}

int get_size(node* v) {
  splay(v);
  return (v != NULL ? v->sz : 0);
}

template<typename... T>
void apply(node* v, T... args) {
  splay(v);
  v->unsafe_apply(args...);
}

void reverse(node* v) {
  splay(v);
  v->unsafe_reverse();
}
}

using namespace splay_tree;

const int N = 1234567;

int n, m, q, a[N], l[N], r[N], tl[N], tr[N], tv[N], cur[N];
node* root = NULL;
vector<int> ev[N];
node* erased[N];
set<int> st[N];

void add(int x, int l, int r, int ll, int rr, int i) {
  if (ll <= l && r <= rr) {
    ev[x].push_back(i);
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    if (ll <= y) {
      add(x + 1, l, y, ll, rr, i);
    }
    if (rr > y) {
      add(z, y + 1, r, ll, rr, i);
    }
  }
}

void solve(int x, int l, int r) {
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    node* v = new node(tl[i], tr[i], tv[i]);
    if (middle != NULL) {
      v->tl = min(v->tl, middle->ml);
      v->tr = max(v->tr, middle->mr);
      v->tv = max(v->tv, middle->mv);
      v->pull();
    }
    erased[i] = middle;
    root = merge(left, merge(v, right));
  }
  reverse(ev[x].begin(), ev[x].end());
  if (l == r) {
    cout << (n - root->sm) << "\n";
  } else {
    int y = (l + r) >> 1, z = x + ((y - l + 1) << 1);
    solve(x + 1, l, y);
    solve(z, y + 1, r);
  }
  for (int i : ev[x]) {
    node* left;
    node* middle;
    node* right;
    node* temp;
    tie(left, temp) = split(root, [&](node* v) { return v->tr >= tl[i]; });
    tie(middle, right) = split(temp, [&](node* v) { return v->tl > tr[i]; });
    root = merge(left, merge(erased[i], right));
    delete middle;
  }
}

int main() {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    st[a[i]].insert(i);
  }
  for (int i = 0; i < N; ++i) {
    if (!st[i].empty()) {
      cur[i] = m;
      tl[m] = *st[i].begin();
      tr[m] = *st[i].rbegin();
      tv[m] = st[i].size();
      l[m] = 0;
      r[m] = q;
      m++;
    } else {
      cur[i] = -1;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int p;
    cin >> p;
    --p;
    st[a[p]].erase(p);
    r[cur[a[p]]] = i - 1;
    if (!st[a[p]].empty()) {
      cur[a[p]] = m;
      tl[m] = *st[a[p]].begin();
      tr[m] = *st[a[p]].rbegin();
      tv[m] = st[a[p]].size();
      l[m] = i;
      r[m] = q;
      m++;
    } else {
      cur[a[p]] = -1;
    }
    cin >> a[p];
    st[a[p]].insert(p);
    if (cur[a[p]] != -1) {
      r[cur[a[p]]] = i - 1;
    }
    cur[a[p]] = m;
    tl[m] = *st[a[p]].begin();
    tr[m] = *st[a[p]].rbegin();
    tv[m] = st[a[p]].size();
    l[m] = i;
    r[m] = q;
    m++;
  }
  for (int i = 0; i < m; ++i) {
    add(0, 0, q, l[i], r[i], i);
  }
  solve(0, 0, q);
  return 0;
}


#define __AVX__ 1
#define __AVX2__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>
#include<x86intrin.h>

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef long double llf;
typedef std::pair<int,int> pii;

#define xx first
#define yy second

template<typename T> inline T max(T a,T b){return a>b?a:b;}
template<typename T> inline T min(T a,T b){return a<b?a:b;}
template<typename T> inline T abs(T a){return a>0?a:-a;}
template<typename T> inline bool repr(T &a,T b){return a<b?a=b,1:0;}
template<typename T> inline bool repl(T &a,T b){return a>b?a=b,1:0;}
template<typename T> inline T gcd(T a,T b){T t;if(a<b){while(a){t=a;a=b%a;b=t;}return b;}else{while(b){t=b;b=a%b;a=t;}return a;}}
template<typename T> inline T sqr(T x){return x*x;}
#define mp(a,b) std::make_pair(a,b)
#define pb push_back
#define I __attribute__((always_inline))inline
#define mset(a,b) memset(a,b,sizeof(a))
#define mcpy(a,b) memcpy(a,b,sizeof(a))

#define fo0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define fo1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define fo(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define fd0(i,n) for(int i=(n)-1;~i;i--)
#define fd1(i,n) for(int i=n;i;i--)
#define fd(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define foe(i,x)for(__typeof((x).end())i=(x).begin();i!=(x).end();++i)
#define fre(i,x)for(__typeof((x).rend())i=(x).rbegin();i!=(x).rend();++i)

struct Cg{I char operator()(){return getchar();}};
struct Cp{I void operator()(char x){putchar(x);}};
#define OP operator
#define RT return *this;
#define UC unsigned char
#define RX x=0;UC t=P();while((t<'0'||t>'9')&&t!='-')t=P();bool f=0;\
if(t=='-')t=P(),f=1;x=t-'0';for(t=P();t>='0'&&t<='9';t=P())x=x*10+t-'0'
#define RL if(t=='.'){lf u=0.1;for(t=P();t>='0'&&t<='9';t=P(),u*=0.1)x+=u*(t-'0');}if(f)x=-x
#define RU x=0;UC t=P();while(t<'0'||t>'9')t=P();x=t-'0';for(t=P();t>='0'&&t<='9';t=P())x=x*10+t-'0'
#define TR *this,x;return x;
I bool IS(char x){return x==10||x==13||x==' ';}template<typename T>struct Fr{T P;I Fr&OP,(int&x)
{RX;if(f)x=-x;RT}I OP int(){int x;TR}I Fr&OP,(ll &x){RX;if(f)x=-x;RT}I OP ll(){ll x;TR}I Fr&OP,(char&x)
{for(x=P();IS(x);x=P());RT}I OP char(){char x;TR}I Fr&OP,(char*x){char t=P();for(;IS(t);t=P());if(~t){for(;!IS
(t)&&~t;t=P())*x++=t;}*x++=0;RT}I Fr&OP,(lf&x){RX;RL;RT}I OP lf(){lf x;TR}I Fr&OP,(llf&x){RX;RL;RT}I OP llf()
{llf x;TR}I Fr&OP,(uint&x){RU;RT}I OP uint(){uint x;TR}I Fr&OP,(ull&x){RU;RT}I OP ull(){ull x;TR}};Fr<Cg>in;
#define WI(S) if(x){if(x<0)P('-'),x=-x;UC s[S],c=0;while(x)s[c++]=x%10+'0',x/=10;while(c--)P(s[c]);}else P('0')
#define WL if(y){lf t=0.5;for(int i=y;i--;)t*=0.1;if(x>=0)x+=t;else x-=t,P('-');*this,(ll)(abs(x));P('.');if(x<0)\
x=-x;while(y--){x*=10;x-=floor(x*0.1)*10;P(((int)x)%10+'0');}}else if(x>=0)*this,(ll)(x+0.5);else *this,(ll)(x-0.5);
#define WU(S) if(x){UC s[S],c=0;while(x)s[c++]=x%10+'0',x/=10;while(c--)P(s[c]);}else P('0')
template<typename T>struct Fw{T P;I Fw&OP,(int x){WI(10);RT}I Fw&OP()(int x){WI(10);RT}I Fw&OP,(uint x){WU(10);RT}
I Fw&OP()(uint x){WU(10);RT}I Fw&OP,(ll x){WI(19);RT}I Fw&OP()(ll x){WI(19);RT}I Fw&OP,(ull x){WU(20);RT}I Fw&OP()
(ull x){WU(20);RT}I Fw&OP,(char x){P(x);RT}I Fw&OP()(char x){P(x);RT}I Fw&OP,(const char*x){while(*x)P(*x++);RT}
I Fw&OP()(const char*x){while(*x)P(*x++);RT}I Fw&OP()(lf x,int y){WL;RT}I Fw&OP()(llf x,int y){WL;RT}};Fw<Cp>out;

const int N=200007,Br=112,B=Br+3,BC=N/Br+7;

std::set<int>p[N];
int n,m,blo,bc,s[N],su[N],lst[N],cnt[N];

int gmax[BC];

struct cv_t
{
	int maxv,tcnt,ans;
}cv[BC][B];

//final max is known -> gmax
//each (t,tcnt) before
//1. should tcnt be count -> if yes, max(??, tcnt)
//2. final tcnt
//3. ans in middle

const int B8=(B+7)/8+1,BU=B8*8;
//int maxv[B],tcnt[B],ans[B];
//__m256i _maxv[B8],_tcnt[B8],_ans[B8];
//int*maxv=(int*)_maxv,*tcnt=(int*)_tcnt,*ans=(int*)_ans;
__attribute__((__aligned__(32))) int maxv[BU],tcnt[BU],ans[BU];
__m256i*_maxv=(__m256i*)maxv,*_tcnt=(__m256i*)tcnt,*_ans=(__m256i*)ans;

//int UFLAG;

void build(int x)
{
	//assert(reinterpret_cast<ull>(ans)%32==0);
	//out,"build:",x,'\n';
	int l=x*blo-blo+1,r=min(n,x*blo);
	int tmax=l-1,lsumd=l-1;
	fo(i,0,r+1-l)tcnt[i]=ans[i]=0,maxv[i]=-1;
	int le8=(r+2-l+7)/8;
	//assert((r+1-l+7)/8<le8);
	//assert(le8<=B8);
	fo(i,l,r)
	{
		if(!su[i])continue;
		//out,"process:",i,'\n';
		repr(tmax,lst[su[i]]);
		int C=cnt[su[i]];
		//out,C,'\n';
		__m256i cnt8=_mm256_set_epi32(C,C,C,C,C,C,C,C);
		//fo(j,l,r+1)repr(tcnt[j-l],cnt[su[i]]);
		//fo(j,l,r+1)repr(tcnt[j-l],C);
		//int tcnt2[B];
		//fo0(j,r+2-l)tcnt2[j]=max(tcnt[j],C);
		fo0(j,r+2-l)repr(tcnt[j],C);
		//fo0(j,le8)_tcnt[j]=_mm256_max_epi32(_tcnt[j],cnt8);
		//out,'/',le8,'\n';
		//fo0(j,r+2-l)assert(tcnt2[j]==tcnt[j]);
		//if(x==1){fo0(j,r+1-l)out,tcnt[j],' ';out,'\n';}
		if(tmax==i)
		{
			int L,R;

			//L=0,R=lsumd-l+1;
			//while(R&7)R--,ans[R]+=tcnt[R];
			//if(R)fo0(j,R>>3)_ans[j]=_mm256_add_epi32(_ans[j],_tcnt[j]);
			fo(j,l,lsumd)ans[j-l]+=tcnt[j-l];
			//while(R--)ans[R]+=tcnt[R];

			//L=lsumd-l+1,R=i-l+1;
			//while(L&7)maxv[L]=tcnt[L],L++;
			//while(R&7)R--,maxv[L]=tcnt[R];
			//fo(j,L>>3,(R>>3)-1)_maxv[j]=_tcnt[j];
			fo(j,lsumd+1,i)maxv[j-l]=tcnt[j-l];

			//L=0,R=i-l+1;
			//while(R&7)R--,tcnt[R]=0;
			//fo0(j,R>>3)_tcnt[j]=_mm256_setzero_si256();
			fo(j,l,i)tcnt[j-l]=0;

			/*fo(j,l,lsumd)
			{
				ans[j-l]+=tcnt[j-l];
				tcnt[j-l]=0;
			}
			fo(j,lsumd+1,i)
			{
				maxv[j-l]=tcnt[j-l];
				tcnt[j-l]=0;
			}*/
			lsumd=i;
		}
		//UFLAG++;
		//fo(j,0,r+1-l)out,maxv[j],' ';out,'\n';
		//fo(j,0,r+1-l)out,tcnt[j],' ';out,'\n';
		//fo(j,0,r+1-l)out,ans[j],' ';out,'\n';
	}
	//fo(j,0,r+1-l)out,tcnt[j],' ';out,'\n';
	//out,1,'\n';
	fo(i,0,r+1-l)
	{
		cv[x][i]=(cv_t){maxv[i],tcnt[i],ans[i]};
		//out,maxv[i],' ',tcnt[i],' ',ans[i],'\n';
	}
	gmax[x]=tmax;
}

inline int get_ans()
{
	int t=0,tcnt=0,ans=0;
	fo1(i,bc)
	{
		int l=i*blo-blo+1,r=min(n,i*blo);
		if(t>r)
		{
			repr(t,gmax[i]);
			repr(tcnt,cv[i][r+1-l].tcnt);
			//out,"/a ",i,' ',t,' ',tcnt,' ',ans,'\n';
			continue;
		}
		repr(t,l);
		if(cv[i][t-l].maxv==-1)
		{
			repr(tcnt,cv[i][t-l].tcnt);
			repr(t,gmax[i]);
			//out,'@',i,' ',t-l,' ',cv[i][t-l].tcnt,'\n';
			//out,"/b ",i,' ',t,' ',tcnt,' ',ans,'\n';
			continue;
		}
		//out,'@',t-l,'\n';
		ans+=max(cv[i][t-l].maxv,tcnt);
		ans+=cv[i][t-l].ans;
		tcnt=cv[i][t-l].tcnt;
		repr(t,gmax[i]);
		//out,"/c ",i,' ',t,' ',tcnt,' ',ans,'\n';
	}
	return ans;
}

inline int geb(int x)
{
	return (x-1)/blo+1;
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	in,n,m;
	//blo=sqrt(n);
	//blo=pow((lf)n,1./3);
	blo=Br;
	bc=(n+blo-1)/blo;
	//out,'/',blo,' ',bc,'\n';
	//blo=2;
	repr(blo,1),repl(blo,n);
	fo1(i,n)in,s[i];
	fo1(i,n)
	{
		if(!lst[s[i]])su[i]=s[i];
		lst[s[i]]=i,cnt[s[i]]++;
		p[s[i]].insert(i);
	}
	fo0(i,N)if(lst[i])su[lst[i]]=i;
	fo1(i,bc)build(i);
	//out,"su:";fo1(j,n)out,su[j],' ';out,'\n';
	//out,"lst:";fo1(j,n)out,lst[j],' ';out,'\n';
	//out,"cnt:";fo1(j,n)out,cnt[j],' ';out,'\n';
	out,n-get_ans(),'\n';
	fo0(i,m)
	{
		int x,y;
		in,x,y;
		//out,'@',x,' ',y,'\n';
		std::set<int>reb;
		if(s[x]!=y)
		{
			int a=s[x],xl=*p[a].begin(),xr=*p[a].rbegin();
			cnt[a]--;
			p[a].erase(x);
			if(!p[a].size())
			{
				reb.insert(geb(xl));
				su[xl]=0;
			}
			else
			{
				int nxl=*p[a].begin(),nxr=*p[a].rbegin();
				if(nxl!=xl)reb.insert(geb(xl)),su[xl]=0,su[nxl]=a;
				if(nxr!=xr)reb.insert(geb(xr)),su[xr]=0,su[nxr]=a;
				lst[a]=nxr;
				reb.insert(geb(nxl)),reb.insert(geb(nxr));
			}
			//out,"reb:";foe(j,reb)out,*j,' ';out,'\n';
			//out,'@',x,' ',y,'\n';
			a=s[x]=y;
			cnt[a]++;
			if(!p[a].size())
			{
				p[a].insert(x);
				reb.insert(geb(x));
				su[x]=a;
				lst[a]=x;
			}
			else
			{
				int nxl=*p[a].begin(),nxr=*p[a].rbegin();
				p[a].insert(x);
				int xl=*p[a].begin(),xr=*p[a].rbegin();
				//out,"====",xl,' ',xr,' ',nxl,' ',nxr,'\n';
				if(nxl!=xl)reb.insert(geb(nxl)),su[xl]=a,nxl==nxr?0:su[nxl]=0;
				if(nxr!=xr)reb.insert(geb(nxr)),su[xr]=a,nxl==nxr?0:su[nxr]=0;
				lst[a]=xr;
				reb.insert(geb(xl)),reb.insert(geb(xr));
			}
			//out,"su:";fo1(j,n)out,su[j],' ';out,'\n';
			//out,"lst:";fo1(j,n)out,lst[j],' ';out,'\n';
			//out,"cnt:";fo1(j,n)out,cnt[j],' ';out,'\n';
			//out,"reb:";foe(j,reb)out,*j,' ';out,'\n';
			foe(j,reb)build(*j);
		}
		out,n-get_ans(),'\n';
	}
	//while(1);
}


#define __AVX__ 1
#define __AVX2__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>
#include<x86intrin.h>

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef long double llf;
typedef std::pair<int,int> pii;

#define xx first
#define yy second

template<typename T> inline T max(T a,T b){return a>b?a:b;}
template<typename T> inline T min(T a,T b){return a<b?a:b;}
template<typename T> inline T abs(T a){return a>0?a:-a;}
template<typename T> inline bool repr(T &a,T b){return a<b?a=b,1:0;}
template<typename T> inline bool repl(T &a,T b){return a>b?a=b,1:0;}
template<typename T> inline T gcd(T a,T b){T t;if(a<b){while(a){t=a;a=b%a;b=t;}return b;}else{while(b){t=b;b=a%b;a=t;}return a;}}
template<typename T> inline T sqr(T x){return x*x;}
#define mp(a,b) std::make_pair(a,b)
#define pb push_back
#define I __attribute__((always_inline))inline
#define mset(a,b) memset(a,b,sizeof(a))
#define mcpy(a,b) memcpy(a,b,sizeof(a))

#define fo0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define fo1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define fo(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define fd0(i,n) for(int i=(n)-1;~i;i--)
#define fd1(i,n) for(int i=n;i;i--)
#define fd(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define foe(i,x)for(__typeof((x).end())i=(x).begin();i!=(x).end();++i)
#define fre(i,x)for(__typeof((x).rend())i=(x).rbegin();i!=(x).rend();++i)

struct Cg{I char operator()(){return getchar();}};
struct Cp{I void operator()(char x){putchar(x);}};
#define OP operator
#define RT return *this;
#define UC unsigned char
#define RX x=0;UC t=P();while((t<'0'||t>'9')&&t!='-')t=P();bool f=0;\
if(t=='-')t=P(),f=1;x=t-'0';for(t=P();t>='0'&&t<='9';t=P())x=x*10+t-'0'
#define RL if(t=='.'){lf u=0.1;for(t=P();t>='0'&&t<='9';t=P(),u*=0.1)x+=u*(t-'0');}if(f)x=-x
#define RU x=0;UC t=P();while(t<'0'||t>'9')t=P();x=t-'0';for(t=P();t>='0'&&t<='9';t=P())x=x*10+t-'0'
#define TR *this,x;return x;
I bool IS(char x){return x==10||x==13||x==' ';}template<typename T>struct Fr{T P;I Fr&OP,(int&x)
{RX;if(f)x=-x;RT}I OP int(){int x;TR}I Fr&OP,(ll &x){RX;if(f)x=-x;RT}I OP ll(){ll x;TR}I Fr&OP,(char&x)
{for(x=P();IS(x);x=P());RT}I OP char(){char x;TR}I Fr&OP,(char*x){char t=P();for(;IS(t);t=P());if(~t){for(;!IS
(t)&&~t;t=P())*x++=t;}*x++=0;RT}I Fr&OP,(lf&x){RX;RL;RT}I OP lf(){lf x;TR}I Fr&OP,(llf&x){RX;RL;RT}I OP llf()
{llf x;TR}I Fr&OP,(uint&x){RU;RT}I OP uint(){uint x;TR}I Fr&OP,(ull&x){RU;RT}I OP ull(){ull x;TR}};Fr<Cg>in;
#define WI(S) if(x){if(x<0)P('-'),x=-x;UC s[S],c=0;while(x)s[c++]=x%10+'0',x/=10;while(c--)P(s[c]);}else P('0')
#define WL if(y){lf t=0.5;for(int i=y;i--;)t*=0.1;if(x>=0)x+=t;else x-=t,P('-');*this,(ll)(abs(x));P('.');if(x<0)\
x=-x;while(y--){x*=10;x-=floor(x*0.1)*10;P(((int)x)%10+'0');}}else if(x>=0)*this,(ll)(x+0.5);else *this,(ll)(x-0.5);
#define WU(S) if(x){UC s[S],c=0;while(x)s[c++]=x%10+'0',x/=10;while(c--)P(s[c]);}else P('0')
template<typename T>struct Fw{T P;I Fw&OP,(int x){WI(10);RT}I Fw&OP()(int x){WI(10);RT}I Fw&OP,(uint x){WU(10);RT}
I Fw&OP()(uint x){WU(10);RT}I Fw&OP,(ll x){WI(19);RT}I Fw&OP()(ll x){WI(19);RT}I Fw&OP,(ull x){WU(20);RT}I Fw&OP()
(ull x){WU(20);RT}I Fw&OP,(char x){P(x);RT}I Fw&OP()(char x){P(x);RT}I Fw&OP,(const char*x){while(*x)P(*x++);RT}
I Fw&OP()(const char*x){while(*x)P(*x++);RT}I Fw&OP()(lf x,int y){WL;RT}I Fw&OP()(llf x,int y){WL;RT}};Fw<Cp>out;

const int N=200007,Br=112,B=Br+3,BC=N/Br+7;

std::set<int>p[N];
int n,m,blo,bc,s[N],su[N],lst[N],cnt[N];

int gmax[BC];

struct cv_t
{
	int maxv,tcnt,ans;
}cv[BC][B];

//final max is known -> gmax
//each (t,tcnt) before
//1. should tcnt be count -> if yes, max(??, tcnt)
//2. final tcnt
//3. ans in middle

const int B8=(B+7)/8+1,BU=B8*8;
__attribute__((__aligned__(32))) int maxv[BU],tcnt[BU],ans[BU];

void build(int x)
{
	int l=x*blo-blo+1,r=min(n,x*blo);
	int tmax=l-1,lsumd=l-1;
	fo(i,0,r+1-l)tcnt[i]=ans[i]=0,maxv[i]=-1;
	fo(i,l,r)
	{
		if(!su[i])continue;
		repr(tmax,lst[su[i]]);
		int C=cnt[su[i]];
		fo0(j,r+2-l)repr(tcnt[j],C);
		if(tmax==i)
		{
			fo(j,l,lsumd)ans[j-l]+=tcnt[j-l];
			fo(j,lsumd+1,i)maxv[j-l]=tcnt[j-l];
			fo(j,l,i)tcnt[j-l]=0;
			lsumd=i;
		}
	}
	fo(i,0,r+1-l)
	{
		cv[x][i]=(cv_t){maxv[i],tcnt[i],ans[i]};
	}
	gmax[x]=tmax;
}

inline int get_ans()
{
	int t=0,tcnt=0,ans=0;
	fo1(i,bc)
	{
		int l=i*blo-blo+1,r=min(n,i*blo);
		if(t>r)
		{
			repr(t,gmax[i]);
			repr(tcnt,cv[i][r+1-l].tcnt);
			continue;
		}
		repr(t,l);
		if(cv[i][t-l].maxv==-1)
		{
			repr(tcnt,cv[i][t-l].tcnt);
			repr(t,gmax[i]);
			continue;
		}
		ans+=max(cv[i][t-l].maxv,tcnt);
		ans+=cv[i][t-l].ans;
		tcnt=cv[i][t-l].tcnt;
		repr(t,gmax[i]);
	}
	return ans;
}

inline int geb(int x)
{
	return (x-1)/blo+1;
}

int main()
{
	in,n,m;
	blo=Br;
	bc=(n+blo-1)/blo;
	repr(blo,1),repl(blo,n);
	fo1(i,n)in,s[i];
	fo1(i,n)
	{
		if(!lst[s[i]])su[i]=s[i];
		lst[s[i]]=i,cnt[s[i]]++;
		p[s[i]].insert(i);
	}
	fo0(i,N)if(lst[i])su[lst[i]]=i;
	fo1(i,bc)build(i);
	out,n-get_ans(),'\n';
	fo0(i,m)
	{
		int x,y;
		in,x,y;
		std::set<int>reb;
		if(s[x]!=y)
		{
			int a=s[x],xl=*p[a].begin(),xr=*p[a].rbegin();
			cnt[a]--;
			p[a].erase(x);
			if(!p[a].size())
			{
				reb.insert(geb(xl));
				su[xl]=0;
			}
			else
			{
				int nxl=*p[a].begin(),nxr=*p[a].rbegin();
				if(nxl!=xl)reb.insert(geb(xl)),su[xl]=0,su[nxl]=a;
				if(nxr!=xr)reb.insert(geb(xr)),su[xr]=0,su[nxr]=a;
				lst[a]=nxr;
				reb.insert(geb(nxl)),reb.insert(geb(nxr));
			}
			a=s[x]=y;
			cnt[a]++;
			if(!p[a].size())
			{
				p[a].insert(x);
				reb.insert(geb(x));
				su[x]=a;
				lst[a]=x;
			}
			else
			{
				int nxl=*p[a].begin(),nxr=*p[a].rbegin();
				p[a].insert(x);
				int xl=*p[a].begin(),xr=*p[a].rbegin();
				if(nxl!=xl)reb.insert(geb(nxl)),su[xl]=a,nxl==nxr?0:su[nxl]=0;
				if(nxr!=xr)reb.insert(geb(nxr)),su[xr]=a,nxl==nxr?0:su[nxr]=0;
				lst[a]=xr;
				reb.insert(geb(xl)),reb.insert(geb(xr));
			}
			foe(j,reb)build(*j);
		}
		out,n-get_ans(),'\n';
	}
}