#include<bits/stdc++.h>

using namespace std;

#define N 300000
#define ls (x<<1)
#define rs (x<<1|1)

int n,m,a[N];
set<int> se[N];

struct node{
	int p1,p2,sum,val,all;
	node(int a=0,int b=0,int c=0,int d=0):p1(a),p2(b),sum(c),val(d),all(d){}
}seg[N<<2];

void MAX(int &x,int y){x=max(x,y);}

void merge(node &p,int x,int l,int r){
	if (!seg[x].p1) return;
	if (l==r){
		if (p.p2>=seg[x].p1){
			MAX(p.p2,seg[x].p2);
			MAX(p.val,seg[x].all);
		}
		else{
			p.p1=seg[x].p1;
			p.p2=seg[x].p2;
			p.sum+=p.val;
			p.val=seg[x].val;
		}
		return;
	}
	int mid=(l+r)>>1;
	if (p.p2>=seg[ls].p1){
		MAX(p.p2,seg[ls].p2);
		MAX(p.val,seg[ls].all);
		merge(p,rs,mid+1,r);
	}
	else{
		merge(p,ls,l,mid);
		p.p1=seg[x].p1;
		p.p2=seg[x].p2;
		p.sum+=seg[x].sum-seg[ls].sum;
		p.val=seg[x].val;
	}
}

void mdf(int x,int l,int r,int t,int k,int o){
	if (l==r){seg[x]=node(t*(k>0),k,0,o); return;}
	int mid=(l+r)>>1;
	if (t<=mid) mdf(ls,l,mid,t,k,o);
	else mdf(rs,mid+1,r,t,k,o);
	seg[x]=seg[ls];
	merge(seg[x],rs,mid+1,r);
}

void ers(int i){
	int c=a[i];
	mdf(1,1,n,*se[c].begin(),0,0);
	se[c].erase(i);
	if (se[c].size())
		mdf(1,1,n,*se[c].begin(),*se[c].rbegin(),se[c].size());
}

void ins(int i){
	int c=a[i];
	if (se[c].size())
		mdf(1,1,n,*se[c].begin(),0,0);
	se[c].insert(i);
	mdf(1,1,n,*se[c].begin(),*se[c].rbegin(),se[c].size());
}

int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i){
		scanf("%d",a+i);
		se[a[i]].insert(i);
	}
	for (int i=1;i<=200000;++i){
		if (se[i].empty()) continue;
		int x=*se[i].begin(),y=*se[i].rbegin(),z=se[i].size();
		mdf(1,1,n,x,y,z);
	}
	printf("%d\n",n-seg[1].sum-seg[1].val);
	for (int i=1;i<=m;++i){
		int x,y; scanf("%d%d",&x,&y);
		ers(x); a[x]=y; ins(x);
		printf("%d\n",n-seg[1].sum-seg[1].val);
	}

	return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define N 300000
#define ls (x<<1)
#define rs (x<<1|1)

int n,m,a[N];
set<int> se[N];

struct node{
	int p1,p2,sum,val;
	node(int a=0,int b=0,int c=0,int d=0):p1(a),p2(b),sum(c),val(d){}
}seg[N<<2];

void MAX(int &x,int y){x=max(x,y);}

void merge(node &p,int x,int l,int r){
	assert(!(p.p1==0&&p.p2!=0));
	if (!seg[x].p1) return;
	if (l==r){
		if (p.p2>=seg[x].p1){
			MAX(p.p2,seg[x].p2);
			MAX(p.val,seg[x].val);
		}
		else{
			p.p1=seg[x].p1;
			p.p2=seg[x].p2;
			p.sum+=p.val;
			p.val=seg[x].val;
		}
		return;
	}
	int mid=(l+r)>>1;
	if (p.p2>=seg[ls].p1){
		MAX(p.p2,seg[ls].p2);
		MAX(p.val,seg[ls].val);
		merge(p,rs,mid+1,r);
	}
	else{
		merge(p,ls,l,mid);
		p.p1=seg[x].p1;
		p.p2=seg[x].p2;
		p.sum+=seg[x].sum-seg[ls].sum;
		p.val=seg[x].val;
	}
}

void mdf(int x,int l,int r,int t,int k,int o){
	if (l==r){seg[x]=node(t*(k>0),k,0,o); return;}
	int mid=(l+r)>>1;
	if (t<=mid) mdf(ls,l,mid,t,k,o);
	else mdf(rs,mid+1,r,t,k,o);
	seg[x]=seg[ls];
	merge(seg[x],rs,mid+1,r);
}

void ers(int i){
	int c=a[i];
	mdf(1,1,n,*se[c].begin(),0,0);
	se[c].erase(i);
	if (se[c].size())
		mdf(1,1,n,*se[c].begin(),*se[c].rbegin(),se[c].size());
}

void ins(int i){
	int c=a[i];
	if (se[c].size())
		mdf(1,1,n,*se[c].begin(),0,0);
	se[c].insert(i);
	mdf(1,1,n,*se[c].begin(),*se[c].rbegin(),se[c].size());
}

int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i){
		scanf("%d",a+i);
		se[a[i]].insert(i);
	}
	for (int i=1;i<=200000;++i){
		if (se[i].empty()) continue;
		int x=*se[i].begin(),y=*se[i].rbegin(),z=se[i].size();
		mdf(1,1,n,x,y,z);
	}
	printf("%d\n",n-seg[1].sum-seg[1].val);
	for (int i=1;i<=m;++i){
		int x,y; scanf("%d%d",&x,&y);
		ers(x); a[x]=y; ins(x);
		printf("%d\n",n-seg[1].sum-seg[1].val);
	}

	return 0;
}


#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <string>
#include <set>
#include <map>
#include <random>
#include <bitset>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <deque>
#include <queue>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()

using namespace std;
using ll = long long;
using ul = unsigned long long;
using ld = long double;

struct f {
    int mn, mx, mod, lx, rx, sx;

    f operator+(f x) {
        if (mn < x.mn)
            return {mn, max(mx, x.mx), 0, lx, max(rx, x.mx), sx};
        if (mn > x.mn)
            return {x.mn, max(mx, x.mx), 0, max(mx, x.lx), x.rx, x.sx};
        return {mn, max(mx, x.mx), 0, lx, x.rx, sx + x.sx + max(rx, x.lx)};
    }
};

const int N = 1 << 18;
int a[N], ps[N], n;
set<int> ls[N];
f t[N * 2];

void push(int v) {
    t[v].mn += t[v].mod;
    if (v < N) {
        t[v * 2].mod += t[v].mod;
        t[v * 2 + 1].mod += t[v].mod;
    }
    t[v].mod = 0;
}

void rel(int v) {
    t[v] = t[v * 2] + t[v * 2 + 1];
}

void add(int cl, int cr, int d, int v=1, int l=0, int r=N) {
    if (cr <= l || r <= cl) {
        push(v);
        return;
    }
    if (cl <= l && r <= cr) {
        t[v].mod += d;
        push(v);
        return;
    }
    push(v);
    add(cl, cr, d, v * 2, l, (l + r) / 2);
    add(cl, cr, d, v * 2 + 1, (l + r) / 2, r);
    rel(v);
}

int qu() {
    return n - (t[1].lx + t[1].rx + t[1].sx);
}

void cx(int p, int x, int v=1, int l=0, int r=N) {
    push(v);
    if (r - l == 1) {
        t[v].lx = t[v].mx = x;
        return;
    }
    if (p < (l + r) / 2) {
        cx(p, x, v * 2, l, (l + r) / 2);
        push(v * 2 + 1);
    }
    else {
        push(v * 2);
        cx(p, x, v * 2 + 1, (l + r) / 2, r);
    }
    rel(v);
}

int main() {
#ifdef ONPC
    freopen("a.in", "r", stdin);
#endif
    ios_base::sync_with_stdio(0); cin.tie(0);
	int q, p, x;
    cin >> n >> q;
    rep(i, N) {
        if (i < n)
            cin >> a[i];
        else
            a[i] = N - 1;
        ls[a[i]].insert(i);
    }
    n = N;
    rep(i, n)
        if (i == *ls[a[i]].begin())
            t[N + i].lx = t[N + i].mx = ls[a[i]].size();
    for (int i = N - 1; i; i--)
        rel(i);
    rep(i, N)
        if (!ls[i].empty())
            add(*ls[i].begin(), *--ls[i].end(), 1);
    cout << qu() << '\n';
    rep(z, q) {
        cin >> p >> x;
        p--;
        cx(*ls[a[p]].begin(), 0);
        add(*ls[a[p]].begin(), *--ls[a[p]].end(), -1);
        ls[a[p]].erase(p);
        if (!ls[a[p]].empty()) {
            add(*ls[a[p]].begin(), *--ls[a[p]].end(), 1);
            cx(*ls[a[p]].begin(), ls[a[p]].size());
        }
        if (!ls[x].empty()) {
            add(*ls[x].begin(), *--ls[x].end(), -1);
            cx(*ls[x].begin(), 0);
        }
        ls[x].insert(p);
        add(*ls[x].begin(), *--ls[x].end(), 1);
        cx(*ls[x].begin(), ls[x].size());
        a[p] = x;
        cout << qu() << '\n';
    }
    for (int i = 1; i < N; i++)
        push(i);
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN], lst[MAXN], nxt[MAXN], cnt[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, sm=0, mxsuf=0, mxpre=0, lz=0;
} seg[MAXN*4];

void build(int l, int r, int k) {
	if (l == r)
		return;
	int m = (l+r) / 2;
	build(l,m,k*2);
	build(m+1,r,k*2+1);
}

void merge(node& x, node& y, node& z) {
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	if (y.mx == 0 || z.mx == 0)
		x.sm = y.sm+z.sm;
	else
		x.sm = y.sm+z.sm-min(y.mxsuf,z.mxpre);
	x.mxpre = y.mxpre;
	x.mxsuf = z.mxsuf;
	if (y.mi != 0)
		x.mxpre = max(x.mxpre, z.mxpre);
	if (z.mi != 0)
		x.mxsuf = max(x.mxsuf, y.mxsuf);
}

void prop(int l, int r, int k) {
	if (l != r) {
		seg[2*k].mi += seg[k].lz;
		seg[2*k].mx += seg[k].lz;
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].mi += seg[k].lz;
		seg[2*k+1].mx += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
		merge(seg[k],seg[k*2],seg[k*2+1]);
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].mi += v;
		seg[k].mx += v;
		seg[k].lz += v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].sm += v;
		seg[k].mxsuf += v;
		seg[k].mxpre += v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void qry(int l, int r, int k) {
	if (seg[k].lz) prop(l,r,k);
	if (l == r) {
		//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
		return;
	}
	int m = (l+r) / 2;
	qry(l, m, k*2);
	qry(m+1, r, k*2+1);
	merge(seg[k],seg[k*2],seg[k*2+1]);
	//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
}

int main() {
	mem(lst,0x3f);
	mem(nxt,-1);
	int n, q; scanf("%d %d", &n, &q);
	build(0,n-1,1);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++) {
		if (pos[i].empty())
			continue;
		if ((int)pos[i].size() > 1)
			updAdd(0, n-1, 1, *pos[i].begin(), *(--pos[i].end())-1, 1);
		upd(0, n-1, 1, *pos[i].begin(), (int)pos[i].size());
	}
	//qry(0,n-1,1);
	pri(n-seg[1].sm);
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-seg[1].sm);
			continue;
		}
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, -1);
		upd(0, n-1, 1, *pos[y].begin(), -(int)pos[y].size());
		if (!pos[x].empty()) {
			if ((int)pos[x].size() > 1)
				updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, -1);
			upd(0, n-1, 1, *pos[x].begin(), -(int)pos[x].size());
		}

		pos[y].erase(pos[y].find(idx));
		pos[x].insert(idx);
		a[idx] = x;

		if (!pos[y].empty()) {
			if ((int)pos[y].size() > 1)
				updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, 1);
			upd(0, n-1, 1, *pos[y].begin(), (int)pos[y].size());
		}
		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, 1);
		upd(0, n-1, 1, *pos[x].begin(), (int)pos[x].size());
		//if (i % 310 == 0)
		//	qry(0,n-1,1);
		pri(n-seg[1].sm);
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, lst=0, sm=0, mxsuf=-INF, mxpre=-INF, lz=0;
} seg[MAXN*4];

void merge(node& x, node y, node z) {
	if (y.mi < z.mi)
		z.mxpre = z.mxsuf = -INF, z.sm = 0;
	if (z.mi < y.mi)
		y.mxpre = y.mxsuf = -INF, y.sm = 0;
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	x.lst = z.lst;
	x.sm = y.sm+z.sm;
	if (x.mi == y.lst) {
		if (y.mxpre < 0)
			x.mxpre = y.mx;
		else {
			x.mxpre = y.mxpre;
			x.sm += y.mxsuf;
		}
		if (z.mxsuf < 0)
			x.mxsuf = z.mx;
		else {
			x.mxsuf = z.mxsuf;
			x.sm += z.mxpre;
		}
	} else {
		if (y.mxpre < 0 && z.mxsuf < 0)
			x.mxpre = x.mxsuf = -INF;
		else if (y.mxpre < 0)
			x.mxpre = max(y.mx, z.mxpre), x.mxsuf = z.mxsuf;
		else if (z.mxsuf < 0)
			x.mxsuf = max(z.mx, y.mxsuf), x.mxpre = y.mxpre;
		else
			x.mxpre = y.mxpre, x.mxsuf = z.mxsuf, x.sm += max(y.mxsuf, z.mxpre);
	}
}

void prop(int l, int r, int k) {
	seg[k].mi += seg[k].lz;
	seg[k].lst += seg[k].lz;
	if (l != r) {
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].lz = v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].mx = v;
		seg[k].mi = seg[k].lst;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

int n, q;

void add(int v, int s) {
	if (pos[v].empty())
		return;
	if (s == 1) {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, 1);
		upd(0, n-1, 1, *pos[v].begin(), (int)pos[v].size());
	} else {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, -1);
		upd(0, n-1, 1, *pos[v].begin(), 0);
	}
}

int qry() {
	if (seg[1].mxpre < 0)
		return seg[1].mx;
	return seg[1].sm + seg[1].mxpre + seg[1].mxsuf;
}

int main() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++)
		add(i, 1);
	pri(n-qry());
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-qry());
			continue;
		}
		add(y, -1);
		add(x, -1);
		pos[y].erase(idx);
		a[idx] = x;
		pos[x].insert(idx);
		add(y, 1);
		add(x, 1);
		pri(n-qry());
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, lst=0, sm=0, mxsuf=-INF, mxpre=-INF, lz=0;
} seg[MAXN*4];

void merge(node& x, node y, node z) {
	if (y.mi < z.mi)
		z.mxpre = z.mxsuf = -INF, z.sm = 0;
	if (z.mi < y.mi)
		y.mxpre = y.mxsuf = -INF, y.sm = 0;
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	x.lst = z.lst;
	x.sm = y.sm+z.sm;
	if (x.mi == y.lst) {
		x.mxpre = max(y.mxpre, y.mx);
		x.mxsuf = max(z.mxsuf, z.mx);
		x.sm += max(0, y.mxsuf);
		x.sm += max(0, z.mxpre);
	} else {
		if (y.mxpre < 0 && z.mxsuf < 0) // -||-|-||-
			x.mxpre = x.mxsuf = -INF;
		else if (y.mxpre < 0) // -||-|-0-||-
			x.mxpre = max(y.mx, z.mxpre), x.mxsuf = z.mxsuf;
		else if (z.mxsuf < 0) // -||-0-|-||-
			x.mxsuf = max(z.mx, y.mxsuf), x.mxpre = y.mxpre;
		else // -||-0-|-0-||-
			x.mxpre = y.mxpre, x.mxsuf = z.mxsuf, x.sm += max(y.mxsuf, z.mxpre);
	}
}

void prop(int l, int r, int k) {
	seg[k].mi += seg[k].lz;
	seg[k].lst += seg[k].lz;
	if (l != r) {
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].lz = v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].mx = v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

int n, q;

void add(int v, int s) {
	if (pos[v].empty())
		return;
	if (s == 1) {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, 1);
		upd(0, n-1, 1, *pos[v].begin(), (int)pos[v].size());
	} else {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, -1);
		upd(0, n-1, 1, *pos[v].begin(), 0);
	}
}

int qry() {
	if (seg[1].mxpre < 0)
		return seg[1].mx;
	return seg[1].sm + seg[1].mxpre + seg[1].mxsuf;
}

int main() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++)
		add(i, 1);
	pri(n-qry());
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-qry());
			continue;
		}
		add(y, -1);
		add(x, -1);
		pos[y].erase(idx);
		a[idx] = x;
		pos[x].insert(idx);
		add(y, 1);
		add(x, 1);
		pri(n-qry());
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN], lst[MAXN], nxt[MAXN], cnt[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, sm=0, mxsuf=0, mxpre=0, len=0, lz=0;
} seg[MAXN*4];

void build(int l, int r, int k) {
	seg[k].len = r-l+1;
	if (l == r)
		return;
	int m = (l+r) / 2;
	build(l,m,k*2);
	build(m+1,r,k*2+1);
}

void merge(node& x, node& y, node& z) {
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	if (y.mi == 0 && y.mx == 0)
		x.sm = y.sm+z.sm;
	else if (z.mi == 0 && z.mx == 0)
		x.sm = y.sm+z.sm;
	else
		x.sm = y.sm+z.sm-min(y.mxsuf,z.mxpre);
	x.mxpre = y.mxpre;
	x.mxsuf = z.mxsuf;
	if (y.mi != 0)
		x.mxpre = max(x.mxpre, z.mxpre);
	if (z.mi != 0)
		x.mxsuf = max(x.mxsuf, y.mxsuf);
}

void prop(int l, int r, int k) {
	if (l != r) {
		seg[2*k].mi += seg[k].lz;
		seg[2*k].mx += seg[k].lz;
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].mi += seg[k].lz;
		seg[2*k+1].mx += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
		merge(seg[k],seg[k*2],seg[k*2+1]);
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].mi += v;
		seg[k].mx += v;
		seg[k].lz += v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].sm += v;
		seg[k].mxsuf += v;
		seg[k].mxpre += v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void qry(int l, int r, int k) {
	if (seg[k].lz) prop(l,r,k);
	if (l == r) {
		//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
		return;
	}
	int m = (l+r) / 2;
	qry(l, m, k*2);
	qry(m+1, r, k*2+1);
	merge(seg[k],seg[k*2],seg[k*2+1]);
	//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
}

int main() {
	mem(lst,0x3f);
	mem(nxt,-1);
	int n, q; scanf("%d %d", &n, &q);
	build(0,n-1,1);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++) {
		if (pos[i].empty())
			continue;
		if ((int)pos[i].size() > 1)
			updAdd(0, n-1, 1, *pos[i].begin(), *(--pos[i].end())-1, 1);
		upd(0, n-1, 1, *pos[i].begin(), (int)pos[i].size());
	}
	//qry(0,n-1,1);
	pri(n-seg[1].sm);
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-seg[1].sm);
			continue;
		}
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, -1);
		upd(0, n-1, 1, *pos[y].begin(), -(int)pos[y].size());
		pos[y].erase(pos[y].find(idx));
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, 1);
		if (!pos[y].empty())
			upd(0, n-1, 1, *pos[y].begin(), (int)pos[y].size());

		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, -1);
		if (!pos[x].empty())
			upd(0, n-1, 1, *pos[x].begin(), -(int)pos[x].size());
		pos[x].insert(idx);
		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, 1);
		upd(0, n-1, 1, *pos[x].begin(), (int)pos[x].size());
		//qry(0,n-1,1);
		pri(n-seg[1].sm);
		a[idx] = x;
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN], lst[MAXN], nxt[MAXN], cnt[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, sm=0, mxsuf=0, mxpre=0, len=0, lz=0;
} seg[MAXN*4];

void build(int l, int r, int k) {
	seg[k].len = r-l+1;
	if (l == r)
		return;
	int m = (l+r) / 2;
	build(l,m,k*2);
	build(m+1,r,k*2+1);
}

void merge(node& x, node& y, node& z) {
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	if (y.mi == 0 && y.mx == 0)
		x.sm = y.sm+z.sm;
	else if (z.mi == 0 && z.mx == 0)
		x.sm = y.sm+z.sm;
	else
		x.sm = y.sm+z.sm-min(y.mxsuf,z.mxpre);
	x.mxpre = y.mxpre;
	x.mxsuf = z.mxsuf;
	if (y.mi != 0)
		x.mxpre = max(x.mxpre, z.mxpre);
	if (z.mi != 0)
		x.mxsuf = max(x.mxsuf, y.mxsuf);
}

void prop(int l, int r, int k) {
	if (l != r) {
		seg[2*k].mi += seg[k].lz;
		seg[2*k].mx += seg[k].lz;
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].mi += seg[k].lz;
		seg[2*k+1].mx += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
		merge(seg[k],seg[k*2],seg[k*2+1]);
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].mi += v;
		seg[k].mx += v;
		seg[k].lz += v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].sm += v;
		seg[k].mxsuf += v;
		seg[k].mxpre += v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void qry(int l, int r, int k) {
	if (seg[k].lz) prop(l,r,k);
	if (l == r) {
		//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
		return;
	}
	int m = (l+r) / 2;
	qry(l, m, k*2);
	qry(m+1, r, k*2+1);
	merge(seg[k],seg[k*2],seg[k*2+1]);
	//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
}

int main() {
	mem(lst,0x3f);
	mem(nxt,-1);
	int n, q; scanf("%d %d", &n, &q);
	build(0,n-1,1);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++) {
		if (pos[i].empty())
			continue;
		if ((int)pos[i].size() > 1)
			updAdd(0, n-1, 1, *pos[i].begin(), *(--pos[i].end())-1, 1);
		upd(0, n-1, 1, *pos[i].begin(), (int)pos[i].size());
	}
	//qry(0,n-1,1);
	pri(n-seg[1].sm);
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-seg[1].sm);
			continue;
		}
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, -1);
		upd(0, n-1, 1, *pos[y].begin(), -(int)pos[y].size());
		pos[y].erase(pos[y].find(idx));
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, 1);
		if (!pos[y].empty())
			upd(0, n-1, 1, *pos[y].begin(), (int)pos[y].size());

		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, -1);
		if (!pos[x].empty())
			upd(0, n-1, 1, *pos[x].begin(), -(int)pos[x].size());
		pos[x].insert(idx);
		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, 1);
		upd(0, n-1, 1, *pos[x].begin(), (int)pos[x].size());
		if (i % 317 == 0)
			qry(0,n-1,1);
		pri(n-seg[1].sm);
		a[idx] = x;
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN], lst[MAXN], nxt[MAXN], cnt[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, sm=0, mxsuf=0, mxpre=0, len=0, lz=0;
} seg[MAXN*4];

void build(int l, int r, int k) {
	seg[k].len = r-l+1;
	if (l == r)
		return;
	int m = (l+r) / 2;
	build(l,m,k*2);
	build(m+1,r,k*2+1);
}

void merge(node& x, node& y, node& z) {
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	if (y.mi == 0 && y.mx == 0)
		x.sm = y.sm+z.sm;
	else if (z.mi == 0 && z.mx == 0)
		x.sm = y.sm+z.sm;
	else
		x.sm = y.sm+z.sm-min(y.mxsuf,z.mxpre);
	x.mxpre = y.mxpre;
	x.mxsuf = z.mxsuf;
	if (y.mi != 0)
		x.mxpre = max(x.mxpre, z.mxpre);
	if (z.mi != 0)
		x.mxsuf = max(x.mxsuf, y.mxsuf);
}

void prop(int l, int r, int k) {
	if (l != r) {
		seg[2*k].mi += seg[k].lz;
		seg[2*k].mx += seg[k].lz;
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].mi += seg[k].lz;
		seg[2*k+1].mx += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
		merge(seg[k],seg[k*2],seg[k*2+1]);
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].mi += v;
		seg[k].mx += v;
		seg[k].lz += v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].sm += v;
		seg[k].mxsuf += v;
		seg[k].mxpre += v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void qry(int l, int r, int k) {
	if (seg[k].lz) prop(l,r,k);
	if (l == r) {
		//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
		return;
	}
	int m = (l+r) / 2;
	qry(l, m, k*2);
	qry(m+1, r, k*2+1);
	merge(seg[k],seg[k*2],seg[k*2+1]);
	//cerr << l << " " << r << " " << seg[k].mi << " " << seg[k].sm << " " << seg[k].mxpre << " " << seg[k].mxsuf << "\n";
}

int main() {
	mem(lst,0x3f);
	mem(nxt,-1);
	int n, q; scanf("%d %d", &n, &q);
	build(0,n-1,1);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++) {
		if (pos[i].empty())
			continue;
		if ((int)pos[i].size() > 1)
			updAdd(0, n-1, 1, *pos[i].begin(), *(--pos[i].end())-1, 1);
		upd(0, n-1, 1, *pos[i].begin(), (int)pos[i].size());
	}
	//qry(0,n-1,1);
	pri(n-seg[1].sm);
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-seg[1].sm);
			continue;
		}
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, -1);
		upd(0, n-1, 1, *pos[y].begin(), -(int)pos[y].size());
		pos[y].erase(pos[y].find(idx));
		if ((int)pos[y].size() > 1)
			updAdd(0, n-1, 1, *pos[y].begin(), *(--pos[y].end())-1, 1);
		if (!pos[y].empty())
			upd(0, n-1, 1, *pos[y].begin(), (int)pos[y].size());

		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, -1);
		if (!pos[x].empty())
			upd(0, n-1, 1, *pos[x].begin(), -(int)pos[x].size());
		pos[x].insert(idx);
		if ((int)pos[x].size() > 1)
			updAdd(0, n-1, 1, *pos[x].begin(), *(--pos[x].end())-1, 1);
		upd(0, n-1, 1, *pos[x].begin(), (int)pos[x].size());
		if (i % 310 == 0)
			qry(0,n-1,1);
		pri(n-seg[1].sm);
		a[idx] = x;
	}
	return 0;
}


//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#define mem(a,v) memset((a), (v), sizeof (a))
#define enl printf("\n")
#define case(t) printf("Case #%d: ", (t))
#define ni(n) scanf("%d", &(n))
#define nl(n) scanf("%I64d", &(n))
#define nai(a, n) for (int i = 0; i < (n); i++) ni(a[i])
#define nal(a, n) for (int i = 0; i < (n); i++) nl(a[i])
#define pri(n) printf("%d\n", (n))
#define prl(n) printf("%I64d\n", (n))
#define pii pair<int, int>
#define pil pair<int, long long>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vil vector<pil>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int MOD = 1e9 + 7;
const int INF = 1e9 + 7;
const int MAXN = 2e5 + 5;
const double eps = 1e-9;
int a[MAXN];
set<int> pos[MAXN];

struct node {
	int mi=0, mx=0, lst=0, sm=0, mxsuf=-INF, mxpre=-INF, lz=0;
} seg[MAXN*4];

void merge(node& x, node y, node z) {
	if (y.mi < z.mi)
		z.mxpre = z.mxsuf = -INF, z.sm = 0;
	if (z.mi < y.mi)
		y.mxpre = y.mxsuf = -INF, y.sm = 0;
	x.mi = min(y.mi, z.mi);
	x.mx = max(y.mx, z.mx);
	x.lst = z.lst;
	x.sm = y.sm+z.sm;
	if (x.mi == y.lst) {
		if (y.mxpre < 0)
			x.mxpre = y.mx;
		else
			x.mxpre = y.mxpre;
		if (z.mxsuf < 0)
			x.mxsuf = z.mx;
		else
			x.mxsuf = z.mxsuf;
		//x.mxpre = max(y.mxpre, y.mx);
		//x.mxsuf = max(z.mxsuf, z.mx);
		x.sm += max(0, y.mxsuf);
		x.sm += max(0, z.mxpre);
	} else {
		if (y.mxpre < 0 && z.mxsuf < 0) // -||-|-||-
			x.mxpre = x.mxsuf = -INF;
		else if (y.mxpre < 0) // -||-|-0-||-
			x.mxpre = max(y.mx, z.mxpre), x.mxsuf = z.mxsuf;
		else if (z.mxsuf < 0) // -||-0-|-||-
			x.mxsuf = max(z.mx, y.mxsuf), x.mxpre = y.mxpre;
		else // -||-0-|-0-||-
			x.mxpre = y.mxpre, x.mxsuf = z.mxsuf, x.sm += max(y.mxsuf, z.mxpre);
	}
}

void prop(int l, int r, int k) {
	seg[k].mi += seg[k].lz;
	seg[k].lst += seg[k].lz;
	if (l != r) {
		seg[2*k].lz += seg[k].lz;
		seg[2*k+1].lz += seg[k].lz;
	}
	seg[k].lz = 0;
}

void updAdd(int l, int r, int k, int a, int b, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (b < l || r < a) return;
	if (a <= l && r <= b) {
		seg[k].lz = v;
		prop(l,r,k);
		return;
	}
	int m = (l+r) / 2;
	updAdd(l, m, k*2, a, b, v);
	updAdd(m+1, r, k*2+1, a, b, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

void upd(int l, int r, int k, int a, int v) {
	if (seg[k].lz) prop(l,r,k);
	if (a < l || r < a) return;
	if (a <= l && r <= a) {
		seg[k].mx = v;
		return;
	}
	int m = (l+r) / 2;
	upd(l, m, k*2, a, v);
	upd(m+1, r, k*2+1, a, v);
	merge(seg[k],seg[k*2],seg[k*2+1]);
}

int n, q;

void add(int v, int s) {
	if (pos[v].empty())
		return;
	if (s == 1) {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, 1);
		upd(0, n-1, 1, *pos[v].begin(), (int)pos[v].size());
	} else {
		updAdd(0, n-1, 1, *pos[v].begin(), *(--pos[v].end())-1, -1);
		upd(0, n-1, 1, *pos[v].begin(), 0);
	}
}

int qry() {
	if (seg[1].mxpre < 0)
		return seg[1].mx;
	return seg[1].sm + seg[1].mxpre + seg[1].mxsuf;
}

int main() {
	scanf("%d %d", &n, &q);
	for (int i = 0; i < n; i++) {
		ni(a[i]);
		pos[a[i]].insert(i);
	}
	for (int i = 1; i < MAXN; i++)
		add(i, 1);
	pri(n-qry());
	for (int i = 0; i < q; i++) {
		int idx, x, y;
		scanf("%d %d", &idx, &x);
		idx--;
		y = a[idx];
		if (y == x) {
			pri(n-qry());
			continue;
		}
		add(y, -1);
		add(x, -1);
		pos[y].erase(idx);
		a[idx] = x;
		pos[x].insert(idx);
		add(y, 1);
		add(x, 1);
		pri(n-qry());
	}
	return 0;
}


#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;

#define LL long long
#define debug(x) cerr<<#x<<": "<<x<<endl;
#define fgx cerr<<"--------------"<<endl;
#define dgx cerr<<"=============="<<endl;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int INF = 2147483600;
const int MAXN = 400010;

int N,Q;
LL mn[MAXN<<2],mx[MAXN<<2],lmx[MAXN<<2],rmx[MAXN<<2],ans[MAXN<<2];
LL tag[MAXN<<2];
inline void update(int rt){
	int ls=(rt<<1),rs=(rt<<1|1);
	mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
	if(mn[ls]<mn[rs]){
		mn[rt]=mn[ls]; lmx[rt]=lmx[ls];
		rmx[rt]=max(rmx[ls],mx[rs]);
		ans[rt]=ans[ls];
	} else if(mn[ls]>mn[rs]){
		mn[rt]=mn[rs]; rmx[rt]=rmx[rs];
		lmx[rt]=max(mx[ls],lmx[rs]);
		ans[rt]=ans[rs];
	} else {
		mn[rt]=mn[ls];
		ans[rt]=ans[ls]+ans[rs]+max(rmx[ls],lmx[rs]);
		lmx[rt]=lmx[ls];
		rmx[rt]=rmx[rs];
	} return ;
}
inline void tage_lazy(int rt){
	if(tag[rt]){
		mn[rt<<1]+=tag[rt]; mn[rt<<1|1]+=tag[rt];
		tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt]; tag[rt]=0;
	} return ;
}
inline void Add(int rt,int l,int r,int L,int R,int x){
	if(L<=l&&R>=r){ tag[rt]+=x; mn[rt]+=x; return ; }
	int mid=(l+r)>>1; tage_lazy(rt);
	if(L<=mid) Add(rt<<1,l,mid,L,R,x);
	if(R>mid) Add(rt<<1|1,mid+1,r,L,R,x); update(rt);
}
inline void mdf(int rt,int l,int r,int k,int x){
	if(l==r){ lmx[rt]=x,rmx[rt]=(mn[rt]==0?0:x),mx[rt]=x; return ;}
	int mid=(l+r)>>1; tage_lazy(rt); if(k<=mid) mdf(rt<<1,l,mid,k,x);
	else mdf(rt<<1|1,mid+1,r,k,x); update(rt); return ;
}
set<int> S[MAXN+1];
inline void Erase(int k){
	if(!S[k].size()) return ;
	int l=*S[k].begin(),r=*S[k].rbegin();
	if(l<=r-1) Add(1,1,N-1,l,r-1,-1);
	mdf(1,1,N-1,l,0);
}
inline void Insert(int k){
	if(!S[k].size()) return ;
	int l=*S[k].begin(),r=*S[k].rbegin();
	if(l<=r-1) Add(1,1,N-1,l,r-1,1);
	//fgx;
	mdf(1,1,N-1,l,S[k].size());
	//dgx;
}
int a[MAXN+1];

int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	N=read(),Q=read();
	for(int i=1;i<=N;i++) a[i]=read(),S[a[i]].insert(i);
	for(int i=1;i<=N;i++) Insert(i);
	printf("%I64d\n",N-(mn[1]>0?mx[1]:ans[1]+lmx[1]+rmx[1]));
	while(Q--){
		int x=read(),v=read(); int T=a[x];
		Erase(a[x]); Erase(v);
		S[a[x]].erase(S[a[x]].find(x));
		a[x]=v; S[v].insert(x);
		Insert(T); Insert(v);
		//cout<<mn[1]<<endl;
		printf("%I64d\n",N-(mn[1]>0?mx[1]:ans[1]+lmx[1]+rmx[1])-(S[a[N]].size()==1));
		//fgx;
	}
	return 0;
}
//1 1 1 2 3


#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;

#define LL long long
#define debug(x) cerr<<#x<<": "<<x<<endl;
#define fgx cerr<<"--------------"<<endl;
#define dgx cerr<<"=============="<<endl;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int INF = 2147483600;
const int MAXN = 400010;

int N,Q;
LL mn[MAXN<<2],mx[MAXN<<2],lmx[MAXN<<2],rmx[MAXN<<2],ans[MAXN<<2];
LL tag[MAXN<<2];
inline void update(int rt){
	int ls=(rt<<1),rs=(rt<<1|1);
	mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
	if(mn[ls]<mn[rs]){
		mn[rt]=mn[ls]; lmx[rt]=lmx[ls];
		rmx[rt]=max(rmx[ls],mx[rs]);
		ans[rt]=ans[ls];
	} else if(mn[ls]>mn[rs]){
		mn[rt]=mn[rs]; rmx[rt]=rmx[rs];
		lmx[rt]=max(mx[ls],lmx[rs]);
		ans[rt]=ans[rs];
	} else {
		mn[rt]=mn[ls];
		ans[rt]=ans[ls]+ans[rs]+max(rmx[ls],lmx[rs]);
		lmx[rt]=lmx[ls];
		rmx[rt]=rmx[rs];
	} return ;
}
inline void tage_lazy(int rt){
	if(tag[rt]){
		mn[rt<<1]+=tag[rt]; mn[rt<<1|1]+=tag[rt];
		tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt]; tag[rt]=0;
	} return ;
}
inline void Add(int rt,int l,int r,int L,int R,int x){
	if(L<=l&&R>=r){ tag[rt]+=x; mn[rt]+=x; return ; }
	int mid=(l+r)>>1; tage_lazy(rt);
	if(L<=mid) Add(rt<<1,l,mid,L,R,x);
	if(R>mid) Add(rt<<1|1,mid+1,r,L,R,x); update(rt);
}
inline void mdf(int rt,int l,int r,int k,int x){
	if(l==r){ lmx[rt]=x,rmx[rt]=(mn[rt]==0?0:x),mx[rt]=x; return ;}
	int mid=(l+r)>>1; tage_lazy(rt); if(k<=mid) mdf(rt<<1,l,mid,k,x);
	else mdf(rt<<1|1,mid+1,r,k,x); update(rt); return ;
}
set<int> S[MAXN+1];
inline void Erase(int k){
	if(!S[k].size()) return ;
	int l=*S[k].begin(),r=*S[k].rbegin();
	if(l<=r-1) Add(1,1,N-1,l,r-1,-1);
	mdf(1,1,N-1,l,0);
}
inline void Insert(int k){
	if(!S[k].size()) return ;
	int l=*S[k].begin(),r=*S[k].rbegin();
	if(l<=r-1) Add(1,1,N-1,l,r-1,1);
	//fgx;
	mdf(1,1,N-1,l,S[k].size());
	//dgx;
}
int a[MAXN+1];

int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	N=read(),Q=read();
	for(int i=1;i<=N;i++) a[i]=read(),S[a[i]].insert(i);
	for(int i=1;i<=N;i++) Insert(i);
	printf("%I64d\n",N-(mn[1]>0?mx[1]:ans[1]+lmx[1]+rmx[1])-(S[a[N]].size()==1));
	while(Q--){
		int x=read(),v=read(); int T=a[x];
		Erase(a[x]); Erase(v);
		S[a[x]].erase(S[a[x]].find(x));
		a[x]=v; S[v].insert(x);
		Insert(T); Insert(v);
		printf("%I64d\n",N-(mn[1]>0?mx[1]:ans[1]+lmx[1]+rmx[1])-(S[a[N]].size()==1));
		//fgx;
	}
	return 0;
}
//1 1 1 2 3


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define mp make_pair
#define PI pair<int,int>
#define poly vector<ll>
#define For(i,l,r) for(int i=(int)(l);i<=(int)(r);i++)
#define Rep(i,r,l) for(int i=(int)(r);i>=(int)(l);i--)
#define pb push_back
#define fi first
#define se second
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
	ll x = 0; char ch = gc(); bool positive = 1;
	for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
	for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
	return positive ? x : -x;
}
inline void write(ll a){
    if(a<0){
    	a=-a; putchar('-');
	}
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(ll a){write(a); puts("");}
inline void wri(ll a){write(a); putchar(' ');}
inline ull rnd(){
	return ((ull)rand()<<30^rand())<<4|rand()%4;
}
const int N=200005,M=1<<19|2;
struct data{
	int ans,lm,rm,mn,mx;
}tr[M];
int n,q,lzy[M],a[N];
set<int> s[N];
void push_up(data &c,data a,data b){
	if(a.mn<b.mn){
		c.mn=a.mn;
		c.rm=max(a.rm,b.mx);
		c.lm=a.lm;
		c.ans=a.ans;
	}else if(a.mn>b.mn){
		c.mn=b.mn;
		c.lm=max(b.lm,a.mx);
		c.rm=b.rm;
		c.ans=b.ans;
	}else{
		c.mn=a.mn;
		c.rm=b.rm;
		c.lm=a.lm;
		c.ans=a.ans+b.ans+max(a.rm,b.lm);
	}
	c.mx=max(a.mx,b.mx);
}
void cao(int nod,int x){
	lzy[nod]+=x; tr[nod].mn+=x;
}
void pushdown(int nod){
	if(lzy[nod]){
		cao(nod<<1,lzy[nod]); cao(nod<<1|1,lzy[nod]); lzy[nod]=0;
	}
}
void ins(int l,int r,int i,int j,int de,int nod){
	if(i>j)return;
	if(l==i&&r==j){
		cao(nod,de); return;
	}
	pushdown(nod);
	int mid=(l+r)>>1;
	if(j<=mid)ins(l,mid,i,j,de,nod<<1);
	else if(i>mid)ins(mid+1,r,i,j,de,nod<<1|1);
	else{ins(l,mid,i,mid,de,nod<<1); ins(mid+1,r,mid+1,j,de,nod<<1|1);}
	push_up(tr[nod],tr[nod<<1],tr[nod<<1|1]);
}
void zyk(int l,int r,int pos,int de,int nod){
	if(l==r){
		tr[nod].ans=tr[nod].mx=de; return;
	}
	pushdown(nod);
	int mid=(l+r)>>1;
	if(pos<=mid)zyk(l,mid,pos,de,nod<<1); else zyk(mid+1,r,pos,de,nod<<1|1);
	push_up(tr[nod],tr[nod<<1],tr[nod<<1|1]);
	//if(nod==1)cout<<tr[nod].mn<<" "<<tr[nod<<1].rm<<" "<<tr[nod<<1|1].mn<<endl;
}
void del(int x){
	if(s[x].empty())return;
	ins(1,n,*s[x].begin(),*s[x].rbegin()-1,-1,1);
	zyk(1,n,*s[x].begin(),0,1);
}
void add(int x){//puts("fjz");
	if(s[x].empty())return;
	ins(1,n,*s[x].begin(),*s[x].rbegin()-1,1,1);
	zyk(1,n,*s[x].begin(),s[x].size(),1); //puts("fjt");
}

int main(){
	n=read(),q=read();
	For(i,1,n)s[a[i]=read()].insert(i);
	For(i,1,200000)add(i);
	//cout<<tr[1].ans<<" "<<tr[1].lm<<" "<<tr[1].rm<<endl;
	writeln(n-(tr[1].ans+tr[1].lm+tr[1].rm));
	while(q--){
		int pos=read(),x=read();
		del(a[pos]);
		s[a[pos]].erase(pos);
		add(a[pos]);
		a[pos]=x;
		del(a[pos]);
		s[a[pos]].insert(pos);
		add(a[pos]);
		writeln(n-(tr[1].ans+tr[1].lm+tr[1].rm));
	}

}
/*
5 6
1 1 1 1 3
2 1
4 1
5 3
2 3
4 2
2 1

*/


/***************************************************************
	File name: G.cpp
	Author: ljfcnyali
	Create time: 2020年10月14日 星期三 16时08分45秒
***************************************************************/
#include<bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for ( int i = (a), _end_ = (b); i <= _end_; ++ i )
#define mem(a) memset ( (a), 0, sizeof ( a ) )
#define str(a) strlen ( a )
#define pii pair<int, int>
#define lson root << 1
#define rson root << 1 | 1
typedef long long LL;

const int maxn = 4e5 + 10;

int n, q, a[maxn], ans;
struct node
{
    int l, r; mutable int val;
    bool operator < (const node &a) const { return l < a.l; }
    node(int a = 0, int b = 0, int c = 0) { l = a; r = b; val = c; }
} ;
set<node> Set;
set<int> Col[maxn];
struct Node { multiset<int> Set; int Max, lazy, Min; bool tag; } Tree[maxn << 2];

inline void PushTag(int root, int val)
{
    Tree[root].Min += val; Tree[root].lazy += val;
    Tree[root].tag = Tree[root].Min != 0;
}

inline void PushDown(int root)
{
    if ( !Tree[root].lazy ) return ;
    PushTag(lson, Tree[root].lazy);
    PushTag(rson, Tree[root].lazy);
    Tree[root].lazy = 0;
}

inline void Modify1(int root, int l, int r, int L, int R, int val)
{
    if ( L <= l && r <= R ) { PushTag(root, val); return ; }
    int Mid = l + r >> 1; PushDown(root);
    if ( L <= Mid ) Modify1(lson, l, Mid, L, R, val);
    if ( Mid < R ) Modify1(rson, Mid + 1, r, L, R, val);
    Tree[root].Min = min(Tree[lson].Min, Tree[rson].Min);
    Tree[root].tag = Tree[root].Min != 0;
}

inline void Modify2(int root, int l, int r, int pos, int val)
{
    if ( l == r )
    {
        if ( val > 0 ) Tree[root].Set.insert(val);
        else { auto it = Tree[root].Set.lower_bound(-val); Tree[root].Set.erase(it); }
        Tree[root].Max = Tree[root].Set.size() ? *(-- Tree[root].Set.end()) : 0;
        return ;
    }
    int Mid = l + r >> 1;
    if ( pos <= Mid ) Modify2(lson, l, Mid, pos, val);
    else Modify2(rson, Mid + 1, r, pos, val);
    Tree[root].Max = max(Tree[lson].Max, Tree[rson].Max);
}

inline bool Check(int root, int l, int r, int L, int R)
{
    if ( Tree[root].tag || (L <= l && r <= R) ) return Tree[root].tag;
    int Mid = l + r >> 1; bool op = true; PushDown(root);
    if ( L <= Mid ) op &= Check(lson, l, Mid, L, R);
    if ( Mid < R ) op &= Check(rson, Mid + 1, r, L, R);
    return op;
}

inline int Query(int root, int l, int r, int L, int R)
{
    if ( L <= l && r <= R ) return Tree[root].Max;
    int Mid = l + r >> 1, ret = 0;
    if ( L <= Mid ) ret = max(ret, Query(lson, l, Mid, L, R));
    if ( Mid < R ) ret = max(ret, Query(rson, Mid + 1, r, L, R));
    return ret;
}

inline void change1(int l, int r)
{
    auto it = Set.lower_bound(node(l));
    ans -= (r - l) / 2 + 2 - it -> val;
    Set.erase(it);
}

inline void change2(int l, int r)
{
    int x = Query(1, 1, n + n, l, r);
    ans += (r - l) / 2 + 2 - Query(1, 1, n + n, l, r);
    Set.insert(node(l, r, x));
}

inline void Insert(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin() * 2 + 1, r = *(-- Col[x].end()) * 2 - 1;
    Modify1(1, 1, n + n, l, r, 1);
    Modify2(1, 1, n + n, l, Col[x].size());

    auto it = Set.lower_bound(node(l + 1));
    while ( it != Set.end() && r >= it -> l )
    {
        r = max(r, it -> r);
        change1(it -> l, it -> r);
        it = Set.lower_bound(node(l + 1));
    }
    while ( it != Set.begin() )
    {
        -- it;
        if ( l <= it -> r ) { l = it -> l; r = max(r, it -> r); change1(it -> l, it -> r); }
        else break ;
        it = Set.lower_bound(node(l + 1));
    }
    change2(l, r);
}

inline void Delete(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin() * 2 + 1, r = *(-- Col[x].end()) * 2 - 1;
    Modify1(1, 1, n + n, l, r, -1);
    Modify2(1, 1, n + n, l, -Col[x].size());

    auto it = -- Set.lower_bound(node(l + 1));
    l = it -> l; r = it -> r; change1(l, r);

    for ( int posl = l, posr; posl <= r; posl = posr + 1 )
    {
        int L = posl, R = r; posr = -1;
        while ( L <= R )
        {
            int Mid = L + R >> 1;
            if ( Check(1, 1, n + n, posl, Mid) ) { posr = Mid; L = Mid + 1; }
            else R = Mid - 1;
        }
        if ( posr == -1 ) { posr = posl; continue ; }
        change2(posl, posr);
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &q);
    REP(i, 1, n) { scanf("%d", &a[i]); Col[a[i]].insert(i); }
    REP(i, 1, 200000) Insert(i);
    printf("%d\n", ans);
    while ( q -- )
    {
        int pos, col; scanf("%d%d", &pos, &col);
        Delete(a[pos]); Col[a[pos]].erase(pos); Insert(a[pos]);
        a[pos] = col;
        Delete(a[pos]); Col[a[pos]].insert(pos); Insert(a[pos]);
        printf("%d\n", ans);
    }
    return 0;
}


/***************************************************************
	File name: G.cpp
	Author: ljfcnyali
	Create time: 2020年10月14日 星期三 16时08分45秒
***************************************************************/
#include<bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for ( int i = (a), _end_ = (b); i <= _end_; ++ i )
#define mem(a) memset ( (a), 0, sizeof ( a ) )
#define str(a) strlen ( a )
#define pii pair<int, int>
#define lson root << 1
#define rson root << 1 | 1
typedef long long LL;

const int maxn = 4e5 + 10;

int n, q, a[maxn];
set<int> Col[maxn];
struct node
{
    multiset<int> Set;
    int Max, sum, ans, lazy, Min, lMax, rMax, Fuck;
} Tree[maxn << 2];

inline void PushTag(int root, int val)
{
    Tree[root].Min += val; Tree[root].lazy += val;
    Tree[root].ans = Tree[root].Min ? Tree[root].Max : Tree[root].sum;
}

inline void PushDown(int root)
{
    if ( !Tree[root].lazy ) return ;
    PushTag(lson, Tree[root].lazy);
    PushTag(rson, Tree[root].lazy);
    Tree[root].lazy = 0;
}

inline void PushUp(int root)
{
    Tree[root].Min = min(Tree[lson].Min, Tree[rson].Min);
    Tree[root].Max = max(Tree[lson].Max, Tree[rson].Max);
    if ( Tree[lson].Min < Tree[rson].Min )
    {
        Tree[root].lMax = Tree[lson].lMax;
        Tree[root].rMax = max(Tree[rson].Max, Tree[lson].rMax);
        Tree[root].sum = Tree[lson].sum - Tree[lson].rMax + Tree[root].rMax;
        Tree[root].Fuck = Tree[lson].Fuck;
    }
    else if ( Tree[rson].Min < Tree[lson].Min )
    {
        Tree[root].lMax = max(Tree[lson].Max, Tree[rson].lMax);
        Tree[root].rMax = Tree[rson].rMax;
        Tree[root].sum = Tree[rson].sum - Tree[rson].lMax + Tree[root].lMax;
        Tree[root].Fuck = Tree[rson].Fuck;
    }
    else
    {
        Tree[root].lMax = Tree[lson].lMax;
        Tree[root].rMax = Tree[rson].rMax;
        Tree[root].sum = Tree[lson].sum + Tree[rson].sum - min(Tree[lson].rMax, Tree[rson].lMax);
        Tree[root].Fuck = Tree[lson].Fuck + Tree[rson].Fuck;
        if ( Tree[lson].rMax == 0 && Tree[rson].lMax == 0 ) ++ Tree[root].Fuck;
    }
    Tree[root].ans = Tree[root].Min ? Tree[root].Max : Tree[root].sum;
}

inline void Build(int root, int l, int r)
{
    Tree[root].Fuck = r - l;
    if ( l == r ) return ;
    int Mid = l + r >> 1; Build(lson, l, Mid); Build(rson, Mid + 1, r);
}

inline void Modify1(int root, int l, int r, int L, int R, int val)
{
    if ( L <= l && r <= R ) { PushTag(root, val); return ; }
    int Mid = l + r >> 1; PushDown(root);
    if ( L <= Mid ) Modify1(lson, l, Mid, L, R, val);
    if ( Mid < R ) Modify1(rson, Mid + 1, r, L, R, val);
    PushUp(root);
}

inline void Modify2(int root, int l, int r, int pos, int val)
{
    if ( l == r )
    {
        if ( val > 0 ) Tree[root].Set.insert(val);
        else { auto it = Tree[root].Set.lower_bound(-val); Tree[root].Set.erase(it); }
        Tree[root].Max = Tree[root].Set.size() ? *(-- Tree[root].Set.end()) : 0;
        return ;
    }
    int Mid = l + r >> 1; PushDown(root);
    if ( pos <= Mid ) Modify2(lson, l, Mid, pos, val);
    else Modify2(rson, Mid + 1, r, pos, val);
    PushUp(root);
}

inline void Insert(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin(), r = *(-- Col[x].end()) - 1;
    Modify1(1, 0, n, l, r, 1);
    Modify2(1, 0, n, l, Col[x].size());
}

inline void Delete(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin(), r = *(-- Col[x].end()) - 1;
    Modify1(1, 0, n, l, r, -1);
    Modify2(1, 0, n, l, -Col[x].size());
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &q);
    REP(i, 1, n) { scanf("%d", &a[i]); Col[a[i]].insert(i); }
    Build(1, 0, n);
    REP(i, 1, 200000) Insert(i);
    printf("%d\n", n - Tree[1].Fuck - Tree[1].ans);
    while ( q -- )
    {
        int pos, col; scanf("%d%d", &pos, &col);
        Delete(a[pos]); Col[a[pos]].erase(pos); Insert(a[pos]);
        a[pos] = col;
        Delete(a[pos]); Col[a[pos]].insert(pos); Insert(a[pos]);
        printf("%d\n", n - Tree[1].Fuck - Tree[1].ans);
    }
    return 0;
}


/***************************************************************
	File name: G.cpp
	Author: ljfcnyali
	Create time: 2020年10月14日 星期三 16时08分45秒
***************************************************************/
#include<bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for ( int i = (a), _end_ = (b); i <= _end_; ++ i )
#define mem(a) memset ( (a), 0, sizeof ( a ) )
#define str(a) strlen ( a )
#define pii pair<int, int>
#define lson root << 1
#define rson root << 1 | 1
typedef long long LL;

const int maxn = 4e5 + 10;

int n, q, a[maxn], ans;
struct node
{
    int l, r; mutable int val;
    bool operator < (const node &a) const { return l < a.l; }
    node(int a = 0, int b = 0, int c = 0) { l = a; r = b; val = c; }
} ;
set<node> Set;
set<int> Col[maxn];
struct Node { multiset<int> Set; int Max, lazy, Min; bool tag; } Tree[maxn << 2];

inline void PushTag(int root, int val)
{
    Tree[root].Min += val; Tree[root].lazy += val;
    Tree[root].tag = Tree[root].Min != 0;
}

inline void PushDown(int root)
{
    if ( !Tree[root].lazy ) return ;
    PushTag(lson, Tree[root].lazy);
    PushTag(rson, Tree[root].lazy);
    Tree[root].lazy = 0;
}

inline void Modify1(int root, int l, int r, int L, int R, int val)
{
    if ( L <= l && r <= R ) { PushTag(root, val); return ; }
    int Mid = l + r >> 1; PushDown(root);
    if ( L <= Mid ) Modify1(lson, l, Mid, L, R, val);
    if ( Mid < R ) Modify1(rson, Mid + 1, r, L, R, val);
    Tree[root].Min = min(Tree[lson].Min, Tree[rson].Min);
    Tree[root].tag = Tree[root].Min != 0;
}

inline void Modify2(int root, int l, int r, int pos, int val)
{
    if ( l == r )
    {
        if ( val > 0 ) Tree[root].Set.insert(val);
        else { auto it = Tree[root].Set.lower_bound(-val); Tree[root].Set.erase(it); }
        Tree[root].Max = Tree[root].Set.size() ? *(-- Tree[root].Set.end()) : 0;
        return ;
    }
    int Mid = l + r >> 1;
    if ( pos <= Mid ) Modify2(lson, l, Mid, pos, val);
    else Modify2(rson, Mid + 1, r, pos, val);
    Tree[root].Max = max(Tree[lson].Max, Tree[rson].Max);
}

inline bool Check(int root, int l, int r, int L, int R)
{
    if ( Tree[root].tag || (L <= l && r <= R) ) return Tree[root].tag;
    int Mid = l + r >> 1; bool op = true; PushDown(root);
    if ( L <= Mid ) op &= Check(lson, l, Mid, L, R);
    if ( Mid < R ) op &= Check(rson, Mid + 1, r, L, R);
    return op;
}

inline int Query(int root, int l, int r, int L, int R)
{
    if ( L <= l && r <= R ) return Tree[root].Max;
    int Mid = l + r >> 1, ret = 0;
    if ( L <= Mid ) ret = max(ret, Query(lson, l, Mid, L, R));
    if ( Mid < R ) ret = max(ret, Query(rson, Mid + 1, r, L, R));
    return ret;
}

inline void change1(int l, int r)
{
    auto it = Set.lower_bound(node(l));
    ans -= (r - l) / 2 + 2 - it -> val;
    Set.erase(it);
}

inline void change2(int l, int r)
{
    int x = Query(1, 1, n + n, l, r);
    ans += (r - l) / 2 + 2 - Query(1, 1, n + n, l, r);
    Set.insert(node(l, r, x));
}

inline void Insert(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin() * 2 + 1, r = *(-- Col[x].end()) * 2 - 1;
    Modify1(1, 1, n + n, l, r, 1);
    Modify2(1, 1, n + n, l, Col[x].size());

    auto it = Set.lower_bound(node(l));
    while ( it != Set.end() && r >= it -> l )
    {
        r = max(r, it -> r);
        change1(it -> l, it -> r);
        it = Set.lower_bound(node(l));
    }
    while ( it != Set.begin() )
    {
        -- it;
        if ( l <= it -> r ) { l = it -> l; r = max(r, it -> r); change1(it -> l, it -> r); }
        else break ;
        it = Set.lower_bound(node(l));
    }
    change2(l, r);
}

inline void Delete(int x)
{
    if ( Col[x].size() <= 1 ) return ;
    int l = *Col[x].begin() * 2 + 1, r = *(-- Col[x].end()) * 2 - 1;
    Modify1(1, 1, n + n, l, r, -1);
    Modify2(1, 1, n + n, l, -Col[x].size());

    auto it = -- Set.lower_bound(node(l + 1));
    l = it -> l; r = it -> r; change1(l, r);

    for ( int posl = l, posr; posl <= r; posl = posr + 1 )
    {
        int L = posl, R = r; posr = -1;
        while ( L <= R )
        {
            int Mid = L + R >> 1;
            if ( Check(1, 1, n + n, posl, Mid) ) { posr = Mid; L = Mid + 1; }
            else R = Mid - 1;
        }
        if ( posr == -1 ) { posr = posl; continue ; }
        change2(posl, posr);
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    scanf("%d%d", &n, &q);
    REP(i, 1, n) { scanf("%d", &a[i]); Col[a[i]].insert(i); }
    REP(i, 1, 200000) Insert(i);
    printf("%d\n", ans);
    while ( q -- )
    {
        int pos, col; scanf("%d%d", &pos, &col);
        Delete(a[pos]); Col[a[pos]].erase(pos); Insert(a[pos]);
        a[pos] = col;
        Delete(a[pos]); Col[a[pos]].insert(pos); Insert(a[pos]);
        printf("%d\n", ans);
    }
    return 0;
}


#include <set>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int N = 200000 + 47;
const int T = N << 2 | 47;
const int INF = 0x3f3f3f3f;

int a[N], n, m;
std::set<int> set[N];
int max[T], cov[T], lmax[T], rmax[T], add[T], sum[T];

void input(int &x) {
	char c;
	for(c = getchar(); !isdigit(c); c = getchar()) ;
	for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}

void update(int rt) {
	max[rt] = std::max(max[rt << 1], max[rt << 1 | 1]);
	cov[rt] = (cov[rt << 1] && cov[rt << 1 | 1]) || add[rt];
	if(cov[rt])
		sum[rt] = lmax[rt] = rmax[rt] = max[rt];
	else {
		if(!cov[rt << 1]) lmax[rt] = lmax[rt << 1];
		else lmax[rt] = std::max(max[rt << 1], lmax[rt << 1 | 1]);
		if(!cov[rt << 1 | 1]) rmax[rt] = rmax[rt << 1 | 1];
		else rmax[rt] = std::max(max[rt << 1 | 1], rmax[rt << 1]);
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] -
			std::min(rmax[rt << 1], lmax[rt << 1 | 1]);
	}
}

void ins(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		++add[rt], cov[rt] = 1;
		lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) ins(rt << 1, l, mid, L, R);
	if(R > mid) ins(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void dec(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		--add[rt], cov[rt] = add[rt] > 0;
		if(l != r) update(rt);
		else if(cov[rt]) lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0, sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) dec(rt << 1, l, mid, L, R);
	if(R > mid) dec(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void modify(int rt, int l, int r, int p, int x) {
	if(l == r) {
		max[rt] += x, sum[rt] = max[rt];
		if(cov[rt]) lmax[rt] = rmax[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0;
		return ;
	}
	int mid = l + r >> 1;
	if(p <= mid) modify(rt << 1, l, mid, p, x);
	else modify(rt << 1 | 1, mid + 1, r, p, x);
	update(rt);
}

int main() {

#ifdef Cai
	freopen("s.in", "r", stdin);
#endif

	int x, y, z, l, r;

	input(n), input(m);
	for(int i = 1; i <= n; ++i) input(a[i]);

	for(int i = 1; i <= n; ++i) set[a[i]].insert(i);

	for(int i = 1; i <= n; ++i)
		if(*set[a[i]].begin() == i) {
			modify(1, 1, n, i, set[a[i]].size());
			if(set[a[i]].size() != 1)
				ins(1, 1, n, i, *set[a[i]].rbegin() - 1);
		}

	printf("%d\n", n - sum[1]);

	while(m--) {
		input(x), input(y);
		if(set[a[x]].size() != 1) {
			l = *set[a[x]].begin();
			r = *set[a[x]].rbegin();
			if(l == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, *++set[a[x]].begin(), r - 1);
				z = set[a[x]].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, *++set[a[x]].begin(), z - 1);
			}
			else if(r == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, l, *++set[a[x]].rbegin() - 1);
				modify(1, 1, n, l, -1);
			}
			else
				modify(1, 1, n, l, -1);
			set[a[x]].erase(set[a[x]].find(x));
		}
		else {
			modify(1, 1, n, x, -1);
			set[a[x]].erase(set[a[x]].begin());
		}
		if(set[y].empty())
			modify(1, 1, n, x, 1);
		else {
			l = *set[y].begin();
			r = *set[y].rbegin();
			if(x < l) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, x, r - 1);
				z = set[y].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, x, z + 1);
			}
			else if(x > r) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, l, x - 1);
				modify(1, 1, n, l, 1);
			}
			else
				modify(1, 1, n, l, 1);
		}
		a[x] = y;
		set[y].insert(x);
		printf("%d\n", n - sum[1]);
	}

	return 0;

}


#include <set>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int M = 200000;
const int N = 200000 + 47;
const int T = N << 2 | 47;
const int INF = 0x3f3f3f3f;

int a[N], n, m;
std::set<int> set[N];
int max[T], cov[T], lmax[T], rmax[T], add[T], sum[T];

void input(int &x) {
	char c;
	for(c = getchar(); !isdigit(c); c = getchar()) ;
	for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}

void update(int rt) {
	max[rt] = std::max(max[rt << 1], max[rt << 1 | 1]);
	cov[rt] = (cov[rt << 1] && cov[rt << 1 | 1]) || add[rt];
	if(cov[rt])
		sum[rt] = lmax[rt] = rmax[rt] = max[rt];
	else {
		lmax[rt] = lmax[rt << 1];
		rmax[rt] = rmax[rt << 1 | 1];
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] -
			std::min(rmax[rt << 1], lmax[rt << 1 | 1]);
	}
}

void ins(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		++add[rt], cov[rt] = 1;
		lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) ins(rt << 1, l, mid, L, R);
	if(R > mid) ins(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void dec(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		--add[rt], cov[rt] = add[rt] > 0;
		if(l != r) update(rt);
		else if(cov[rt]) lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0, sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) dec(rt << 1, l, mid, L, R);
	if(R > mid) dec(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void modify(int rt, int l, int r, int p, int x) {
	if(l == r) {
		max[rt] += x, sum[rt] = max[rt];
		if(cov[rt]) lmax[rt] = rmax[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0;
		return ;
	}
	int mid = l + r >> 1;
	if(p <= mid) modify(rt << 1, l, mid, p, x);
	else modify(rt << 1 | 1, mid + 1, r, p, x);
	update(rt);
}

int main() {

#ifdef Cai
	freopen("s.in", "r", stdin);
#endif

	int x, y, z, l, r;

	input(n), input(m);
	for(int i = 1; i <= n; ++i) input(a[i]);

	for(int i = 1; i <= n; ++i) set[a[i]].insert(i);

	for(int i = 1; i <= n; ++i)
		if(*set[a[i]].begin() == i) {
			modify(1, 1, M, i, set[a[i]].size());
			if(set[a[i]].size() != 1)
				ins(1, 1, M, i, *set[a[i]].rbegin() - 1);
		}

	printf("%d\n", n - sum[1]);

	while(m--) {
		input(x), input(y);
		if(set[a[x]].size() != 1) {
			l = *set[a[x]].begin();
			r = *set[a[x]].rbegin();
			if(l == x) {
				dec(1, 1, M, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, M, *++set[a[x]].begin(), r - 1);
				z = set[a[x]].size();
				modify(1, 1, M, l, -z);
				modify(1, 1, M, *++set[a[x]].begin(), z - 1);
			}
			else if(r == x) {
				dec(1, 1, M, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, M, l, *++set[a[x]].rbegin() - 1);
				modify(1, 1, M, l, -1);
			}
			else
				modify(1, 1, M, l, -1);
			set[a[x]].erase(set[a[x]].find(x));
		}
		else {
			modify(1, 1, M, x, -1);
			set[a[x]].erase(set[a[x]].begin());
		}
		if(set[y].empty())
			modify(1, 1, M, x, 1);
		else {
			l = *set[y].begin();
			r = *set[y].rbegin();
			if(x < l) {
				if(set[y].size() != 1)
					dec(1, 1, M, l, r - 1);
				ins(1, 1, M, x, r - 1);
				z = set[y].size();
				modify(1, 1, M, l, -z);
				modify(1, 1, M, x, z + 1);
			}
			else if(x > r) {
				if(set[y].size() != 1)
					dec(1, 1, M, l, r - 1);
				ins(1, 1, M, l, x - 1);
				modify(1, 1, M, l, 1);
			}
			else
				modify(1, 1, M, l, 1);
		}
		a[x] = y;
		set[y].insert(x);
		printf("%d\n", n - sum[1]);
	}

	return 0;

}


#include <set>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int N = 200000 + 47;
const int T = N << 2 | 47;
const int INF = 0x3f3f3f3f;

int a[N], n, m;
std::set<int> set[N];
int max[T], cov[T], lmax[T], rmax[T], add[T], sum[T];

void input(int &x) {
	char c;
	for(c = getchar(); !isdigit(c); c = getchar()) ;
	for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}

void update(int rt) {
	max[rt] = std::max(max[rt << 1], max[rt << 1 | 1]);
	cov[rt] = (cov[rt << 1] & cov[rt << 1 | 1]) || add[rt];
	if(cov[rt])
		sum[rt] = lmax[rt] = rmax[rt] = max[rt];
	else if(cov[rt << 1]) {
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] -
			std::min(max[rt << 1], lmax[rt << 1 | 1]);
		lmax[rt] = std::max(max[rt << 1], lmax[rt << 1 | 1]);
		rmax[rt] = rmax[rt << 1 | 1];
	}
	else if(cov[rt << 1 | 1]) {
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] -
			std::min(max[rt << 1 | 1], rmax[rt << 1]);
		lmax[rt] = lmax[rt << 1];
		rmax[rt] = std::max(max[rt << 1 | 1], rmax[rt << 1]);
	}
	else {
		lmax[rt] = lmax[rt << 1];
		rmax[rt] = rmax[rt << 1 | 1];
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
	}
}

void ins(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		++add[rt], cov[rt] = 1;
		lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) ins(rt << 1, l, mid, L, R);
	if(R > mid) ins(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void dec(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		--add[rt], cov[rt] = add[rt] > 0;
		if(l != r) update(rt);
		else lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) dec(rt << 1, l, mid, L, R);
	if(R > mid) dec(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void modify(int rt, int l, int r, int p, int x) {
	if(l == r) {
		max[rt] += x, sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(p <= mid) modify(rt << 1, l, mid, p, x);
	else modify(rt << 1 | 1, mid + 1, r, p, x);
	update(rt);
}

int main() {

#ifdef Cai
	freopen("s.in", "r", stdin);
#endif

	int x, y, z, l, r;

	input(n), input(m);
	for(int i = 1; i <= n; ++i) input(a[i]);

	for(int i = 1; i <= n; ++i) set[a[i]].insert(i);

	for(int i = 1; i <= n; ++i)
		if(*set[a[i]].begin() == i) {
			modify(1, 1, n, i, set[a[i]].size());
			if(set[a[i]].size() != 1)
				ins(1, 1, n, i, *set[a[i]].rbegin() - 1);
		}

	printf("%d\n", n - sum[1]);

	while(m--) {
		input(x), input(y);
		if(set[a[x]].size() != 1) {
			l = *set[a[x]].begin();
			r = *set[a[x]].rbegin();
			if(l == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, *++set[a[x]].begin(), r - 1);
				z = set[a[x]].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, *++set[a[x]].begin(), z - 1);
			}
			else if(r == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, l, *++set[a[x]].rbegin() - 1);
				modify(1, 1, n, l, -1);
			}
			else
				modify(1, 1, n, l, -1);
			set[a[x]].erase(set[a[x]].find(x));
		}
		else {
			modify(1, 1, n, x, -1);
			set[a[x]].erase(set[a[x]].begin());
		}
		if(set[y].empty())
			modify(1, 1, n, x, 1);
		else {
			l = *set[y].begin();
			r = *set[y].rbegin();
			if(x < l) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, x, r - 1);
				z = set[y].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, x, z + 1);
			}
			else if(x > r) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, l, x - 1);
				modify(1, 1, n, l, 1);
			}
			else
				modify(1, 1, n, l, 1);
		}
		a[x] = y;
		set[y].insert(x);
		printf("%d\n", n - sum[1]);
	}

	return 0;

}


#include <set>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int N = 200000 + 47;
const int T = N << 2 | 47;
const int INF = 0x3f3f3f3f;

int a[N], n, m;
std::set<int> set[N];
int max[T], cov[T], lmax[T], rmax[T], add[T], sum[T];

void input(int &x) {
	char c;
	for(c = getchar(); !isdigit(c); c = getchar()) ;
	for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}

void update(int rt) {
	max[rt] = std::max(max[rt << 1], max[rt << 1 | 1]);
	cov[rt] = (cov[rt << 1] && cov[rt << 1 | 1]) || add[rt];
	if(cov[rt])
		sum[rt] = lmax[rt] = rmax[rt] = max[rt];
	else {
		lmax[rt] = lmax[rt << 1];
		rmax[rt] = rmax[rt << 1 | 1];
		sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] -
			std::min(rmax[rt << 1], lmax[rt << 1 | 1]);
	}
}

void ins(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		++add[rt], cov[rt] = 1;
		lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) ins(rt << 1, l, mid, L, R);
	if(R > mid) ins(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void dec(int rt, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		--add[rt], cov[rt] = add[rt] > 0;
		if(l != r) update(rt);
		else if(cov[rt]) lmax[rt] = rmax[rt] = sum[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0, sum[rt] = max[rt];
		return ;
	}
	int mid = l + r >> 1;
	if(L <= mid) dec(rt << 1, l, mid, L, R);
	if(R > mid) dec(rt << 1 | 1, mid + 1, r, L, R);
	update(rt);
}

void modify(int rt, int l, int r, int p, int x) {
	if(l == r) {
		max[rt] += x, sum[rt] = max[rt];
		if(cov[rt]) lmax[rt] = rmax[rt] = max[rt];
		else lmax[rt] = rmax[rt] = 0;
		return ;
	}
	int mid = l + r >> 1;
	if(p <= mid) modify(rt << 1, l, mid, p, x);
	else modify(rt << 1 | 1, mid + 1, r, p, x);
	update(rt);
}

int main() {

#ifdef Cai
	freopen("s.in", "r", stdin);
#endif

	int x, y, z, l, r;

	input(n), input(m);
	for(int i = 1; i <= n; ++i) input(a[i]);

	for(int i = 1; i <= n; ++i) set[a[i]].insert(i);

	for(int i = 1; i <= n; ++i)
		if(*set[a[i]].begin() == i) {
			modify(1, 1, n, i, set[a[i]].size());
			if(set[a[i]].size() != 1)
				ins(1, 1, n, i, *set[a[i]].rbegin() - 1);
		}

	printf("%d\n", n - sum[1]);

	while(m--) {
		input(x), input(y);
		if(set[a[x]].size() != 1) {
			l = *set[a[x]].begin();
			r = *set[a[x]].rbegin();
			if(l == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, *++set[a[x]].begin(), r - 1);
				z = set[a[x]].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, *++set[a[x]].begin(), z - 1);
			}
			else if(r == x) {
				dec(1, 1, n, l, r - 1);
				if(set[a[x]].size() > 2)
					ins(1, 1, n, l, *++set[a[x]].rbegin() - 1);
				modify(1, 1, n, l, -1);
			}
			else
				modify(1, 1, n, l, -1);
			set[a[x]].erase(set[a[x]].find(x));
		}
		else {
			modify(1, 1, n, x, -1);
			set[a[x]].erase(set[a[x]].begin());
		}
		if(set[y].empty())
			modify(1, 1, n, x, 1);
		else {
			l = *set[y].begin();
			r = *set[y].rbegin();
			if(x < l) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, x, r - 1);
				z = set[y].size();
				modify(1, 1, n, l, -z);
				modify(1, 1, n, x, z + 1);
			}
			else if(x > r) {
				if(set[y].size() != 1)
					dec(1, 1, n, l, r - 1);
				ins(1, 1, n, l, x - 1);
				modify(1, 1, n, l, 1);
			}
			else
				modify(1, 1, n, l, 1);
		}
		a[x] = y;
		set[y].insert(x);
		printf("%d\n", n - sum[1]);
	}

	return 0;

}


#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[200001];
int b[200001];
set<int>s[200001];
struct nd{
    int ans;
    int lz;
    int mn;
    int lmx,rmx,mx;
    nd(){
    	ans=lz=mn=lmx=rmx=mx=0;
	}
	nd(int a,int b,int c,int d,int e,int f){
		ans=a;lz=b;mn=c;lmx=d;rmx=e;mx=f;
	}
};
nd st[524288];
nd pull(nd& x,nd& y){
	nd tot;
	tot.mn=min(x.mn,y.mn);
	if(x.mn==tot.mn) tot.lmx=x.lmx;
	else tot.lmx=max(x.mx,y.lmx);
	if(y.mn==tot.mn) tot.rmx=y.rmx;
	else tot.rmx=max(y.mx,x.rmx);
	tot.mx=max(x.mx,y.mx);
	int lans=(x.mn==tot.mn?x.ans:x.mx);
	int rans=(y.mn==tot.mn?y.ans:y.mx);
	int lr=(x.mn==tot.mn?x.rmx:x.mx);
	int rl=(y.mn==tot.mn?y.lmx:y.mx);
	tot.ans=lans+rans-lr-rl+max(lr,rl);
	return tot;
}
void push(nd& x,nd& y,nd& z){
	y.lz+=x.lz;
	y.mn+=x.lz;
	z.lz+=x.lz;
	z.mn+=x.lz;
	x.lz=0;
}
void upd(int id,int l,int r,int ql,int qr,int v){
	//if(id==1) cout << ql << ' ' << qr << ' ' << v << endl;
	if(l>qr || r<ql) return;
	if(ql<=l && r<=qr){
		st[id].lz+=v;st[id].mn+=v;
		return;
	}
	int mid=(l+r)/2;
	push(st[id],st[id*2],st[id*2+1]);
	upd(id*2,l,mid,ql,qr,v);
	upd(id*2+1,mid+1,r,ql,qr,v);
	st[id]=pull(st[id*2],st[id*2+1]);
}
void ping(int id,int l,int r,int p){
//	cout << "ping " << id << endl;
	if(l==r){
		st[id]={b[l]+b[l+1],st[id].lz,st[id].mn,b[l],b[l+1],max(b[l],b[l+1])};
		return;
	}
	push(st[id],st[id*2],st[id*2+1]);
	int mid=(l+r)/2;
	if(p<=mid) ping(id*2,l,mid,p);
	else ping(id*2+1,mid+1,r,p);
	st[id]=pull(st[id*2],st[id*2+1]);
}
void put(int c,int v){
	if(v==1) b[*s[c].begin()]=s[c].size();
	else b[*s[c].begin()]=0;
	if(*s[c].begin()!=n) ping(1,1,n-1,*s[c].begin());
	if(*s[c].begin()!=1) ping(1,1,n-1,*s[c].begin()-1);
	if(s[c].size()>1) upd(1,1,n-1,*s[c].begin(),*s[c].rbegin()-1,v);
}
int main(){
    ios::sync_with_stdio(false);
    cin >> n >> q;
    if(n==1){
    	for(int i=0; i<=q ;i++) cout << "1\n";
    	return 0;
	}
    for(int i=1; i<=n ;i++){
        cin >> a[i];
        if(!s[a[i]].empty()) put(a[i],-1);
        s[a[i]].insert(i);
        put(a[i],1);
    }
    cout << n-(st[1].mn?st[1].mx:st[1].ans) << '\n';
    for(int i=1; i<=q ;i++){
        int x,y;cin >> x >> y;
        put(a[x],-1);s[a[x]].erase(x);
        if(!s[a[x]].empty()) put(a[x],1);
        a[x]=y;
        if(!s[a[x]].empty()) put(a[x],-1);
        s[a[x]].insert(x);put(a[x],1);
        cout << n-(st[1].mn?st[1].mx:st[1].ans) << '\n';
    }
}


#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[200001];
int b[200001];
set<int>s[200001];
struct nd{
    int ans;
    int lz;
    int mn;
    int lmx,rmx,mx;
};
nd st[524288];
nd pull(nd& x,nd& y){
	nd tot;
	tot.mn=min(x.mn,y.mn);
	if(x.mn==tot.mn) tot.lmx=x.lmx;
	else tot.lmx=max(x.mx,y.lmx);
	if(y.mn==tot.mn) tot.rmx=y.rmx;
	else tot.rmx=max(y.mx,x.rmx);
	tot.mx=max(x.mx,y.mx);
	int lans=(x.mn==tot.mn?x.ans:x.mx);
	int rans=(y.mn==tot.mn?y.ans:y.mx);
	int lr=(x.mn==tot.mn?x.rmx:x.mx);
	int rl=(y.mn==tot.mn?y.lmx:y.mx);
	tot.ans=lans+rans-lr-rl+max(lr,rl);
	return tot;
}
void push(nd& x,nd& y,nd& z){
	y.lz+=x.lz;
	y.mn+=x.lz;
	z.lz+=x.lz;
	z.mn+=x.lz;
	x.lz=0;
}
void upd(int id,int l,int r,int ql,int qr,int v){
	//if(id==1) cout << ql << ' ' << qr << ' ' << v << endl;
	if(l>qr || r<ql) return;
	if(ql<=l && r<=qr){
		st[id].lz+=v;st[id].mn+=v;
		return;
	}
	int mid=(l+r)/2;
	push(st[id],st[id*2],st[id*2+1]);
	upd(id*2,l,mid,ql,qr,v);
	upd(id*2+1,mid+1,r,ql,qr,v);
	st[id]=pull(st[id*2],st[id*2+1]);
}
void ping(int id,int l,int r,int p){
//	cout << "ping " << id << endl;
	if(l==r){
		st[id]={b[l]+b[l+1],st[id].lz,st[id].mn,b[l],b[l+1],max(b[l],b[l+1])};
		return;
	}
	push(st[id],st[id*2],st[id*2+1]);
	int mid=(l+r)/2;
	if(p<=mid) ping(id*2,l,mid,p);
	else ping(id*2+1,mid+1,r,p);
	st[id]=pull(st[id*2],st[id*2+1]);
}
void put(int c,int v){
	if(v==1) b[*s[c].begin()]=s[c].size();
	else b[*s[c].begin()]=0;
	if(*s[c].begin()!=n) ping(1,1,n-1,*s[c].begin());
	if(*s[c].begin()!=1) ping(1,1,n-1,*s[c].begin()-1);
	if(s[c].size()>1) upd(1,1,n-1,*s[c].begin(),*s[c].rbegin()-1,v);
}
int main(){
    ios::sync_with_stdio(false);
    cin >> n >> q;
    if(n==1){
    	for(int i=0; i<=q ;i++) cout << "1\n";
    	return 0;
	}
    for(int i=1; i<=n ;i++){
        cin >> a[i];
        if(!s[a[i]].empty()) put(a[i],-1);
        s[a[i]].insert(i);
        put(a[i],1);
    }
    cout << n-(st[1].mn?st[1].mx:st[1].ans) << '\n';
    for(int i=1; i<=q ;i++){
        int x,y;cin >> x >> y;
        put(a[x],-1);s[a[x]].erase(x);
        if(!s[a[x]].empty()) put(a[x],1);
        a[x]=y;
        if(!s[a[x]].empty()) put(a[x],-1);
        s[a[x]].insert(x);put(a[x],1);
        cout << n-(st[1].mn?st[1].mx:st[1].ans) << '\n';
    }
}


/**************************************************************
    Problem: ????
    User: Big_Red_Dates
    Language: GNU_C++11
    Result: Accepted
    Time:0 ms
    Memory:0 kb
    length:0 kb
    score: inf
****************************************************************/
//CLOCKS_PER_SEC
using namespace std;
#include<bitset>
#include<deque>
#include<stdint.h>
#include<set>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<ctime>
#include<map>
#define sqr(x) (x)*(x)
//#define sort stable_sort
#define ll long long
#define mk make_pair
#define pb push_back
#define in insert
#define mtr(x,y,z) mk(mk(x,y),z)
#define fi first
#define se second
#define lch(x) ((x)<<1)
#define rch(x) (((x)<<1)|1)
#define all(x) (x).begin(),(x).end()
#define titose CLOCKS_PER_SEC
#define fpi(x) freopen(x,"r",stdin);
#define fpo(x) freopen(x,"w",stdout);
#define fprio fpi("in.txt");fpo("out.txt");
#define fast ios_base::sync_with_stdio(false);
inline void read(int &x){int v=0,f=1;char c=getchar();while (!isdigit(c)&&c!='-') c=getchar();if (c=='-') f=-1; else v=(c&15);while (isdigit(c=getchar())) v=(v<<1)+(v<<3)+(c&15);x=v*f;}
inline void read(ll &x){ll v=0ll,f=1ll;char c=getchar();while (!isdigit(c)&&c!='-') c=getchar();if (c=='-') f=-1; else v=(c&15);while (isdigit(c=getchar())) v=(v<<1)+(v<<3)+(c&15);x=v*f;}
inline void readc(char &x){char c;while (((c=getchar())==' ')||c=='\n');x=c;}
inline void writes(string s){puts(s.c_str());}
inline void writeln(){writes("");}
inline void writei(int x){if (x<0){putchar('-');x=abs(x);}if (!x) putchar('0');char a[25];int top=0;while (x){a[++top]=(x%10)+'0';x/=10;}while (top){putchar(a[top]);top--;}}
inline void writell(ll x){if (x<0){putchar('-');x=abs(x);}if (!x) putchar('0');char a[25];int top=0;while (x){a[++top]=(x%10)+'0';x/=10;}while (top){putchar(a[top]);top--;}}
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vl vector<ll>
#define si set<int>
#define sl set<ll>
#define mii map<int,int>
#define mll map<ll,ll>
#define msi map<string,int>
#define msl map<string,ll>
#define piii pair<int,pii >
#define piipi pair<pii,int>
#define plll pair<ll,pll >
#define pllpl pair<pll,ll>
#define pqi priority_queue<int>
#define pql priority_queue<ll>
#define npqi priority_queue<int,vector<int>,greater<int> >
#define npql priority_queue<ll,vector<ll>,greater<ll> >
#define forup(i,a,b) for ((i)=(a);(i)<=(b);(i)++)
#define fordo(i,a,b) for ((i)=(a);(i)>=(b);(i)--)
#define rep(i,x) forup ((i),1,(x))
#define repd(i,x) fordo ((i),(x),1)
#define itr iterator
#define fe(itcalc,c) for(__typeof((c).begin()) itcalc=(c).begin();itcalc!=(c).end();itcalc++)
#define NO {cout<<"NO";return 0;}
#define YES {cout<<"YES";return 0;}
#define y0 y000000000000000000000000000
#define y1 y111111111111111111111111111
#define j0 j000000000000000000000000000
#define j1 j111111111111111111111111111
#define cl0(a) memset((a),(0),(sizeof((a))))
#define clz(a) memset((a),(0x16),(sizeof((a))))
#define clf(a) memset((a),(-(0x16)),(sizeof((a))))
#define inf 0x3bbbbbbb
#define lnf 0x1bbbbbbbbbbbbbbbll
#define sqrt divi
#define p2(i) (1ll<<(i))
#define readi read
#define readll read
/*************************************************/
int n,m,i,j,a[200005];
set<int> s[200005];
struct seg
{
	int mi,mx,l,r,ans,tag;
}t[800005];
void upd(int x,int y)
{
	t[x].mi+=y;
	t[x].tag+=y;
}
void pushdo(int x)
{
	if(t[x].tag){
		upd(x+x,t[x].tag);
		upd(x+x+1,t[x].tag);
		t[x].tag=0;
	}
}
seg mrg(seg x,seg y)
{
	seg ans;ans.tag=0;
	ans.mi=min(x.mi,y.mi);
	ans.mx=max(x.mx,y.mx);
	if(x.mi<y.mi){
		ans.l=x.l;
		ans.r=max(x.r,y.mx);
		ans.ans=x.ans;
	}
	else if(x.mi>y.mi){
		ans.l=max(y.l,x.mx);
		ans.r=y.r;
		ans.ans=y.ans;
	}
	else{
		ans.l=x.l;
		ans.r=y.r;
		ans.ans=x.ans+y.ans+max(x.r,y.l);
	}
	return ans;
}
void pushup(int x)
{
	t[x]=mrg(t[x+x],t[x+x+1]);
}
void update1(int x,int l,int r,int ql,int qr,int c)
{
	if(ql<=l&&r<=qr){
		upd(x,c);
		return;
	}
	pushdo(x);
	int mid=(l+r)/2;
	if(ql<=mid) update1(x+x,l,mid,ql,qr,c);
	if(qr>mid) update1(x+x+1,mid+1,r,ql,qr,c);
	pushup(x);
}
void update2(int x,int l,int r,int y,int c)
{
	if(l==r){
		t[x].mx=t[x].l=c;
		return;
	}
	pushdo(x);
	int mid=(l+r)/2;
	if(y<=mid) update2(x+x,l,mid,y,c);
	if(y>mid) update2(x+x+1,mid+1,r,y,c);
	pushup(x);
}
void ins(int x,int dlt)
{
	if(s[x].empty()) return;
	if(s[x].size()>1) update1(1,0,n,*s[x].begin(),(*s[x].rbegin())-1,dlt);
	update2(1,0,n,*s[x].begin(),(dlt==1?s[x].size():0));
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,n){
		scanf("%d",&a[i]);
		s[a[i]].insert(i);
	}
	rep(i,200000){
		ins(i,1);
	}
	printf("%d\n",n-t[1].ans);
	while(m--){
		int x,y;
		scanf("%d%d",&x,&y);
		ins(a[x],-1);
		s[a[x]].erase(x);
		ins(a[x],1);
		a[x]=y;
		ins(a[x],-1);
		s[a[x]].insert(x);
		ins(a[x],1);
		printf("%d\n",n-t[1].ans);
	}
	return 0;
}


#include <bits/stdc++.h>
#define MAX 200007

using namespace std;
typedef pair<int, int> pii;

struct node {
    int mn, freq;
    int gl, gr;
    int acum, sum;

    node(): mn(0), freq(0), gl(0), gr(0), acum(0), sum(0) {}
} st[4*MAX];

node unhonho(node a, node b){
    node dad;
    dad.mn = min(a.mn, b.mn);
    dad.freq = max(a.freq, b.freq);
    dad.acum = 0;
    if(a.mn < b.mn){ // union the groups
        dad.gl = a.gl;
        dad.gr = max(a.gr, b.freq);
        dad.sum = a.sum - a.gr + dad.gr;
    }else if(a.mn > b.mn){ // union of the groups
        dad.gl = max(a.freq, b.gl);
        dad.gr = b.gr;
        dad.sum = b.sum - b.gl + dad.gl;
    }else{  // sum the answer
        dad.gl = a.gl;
        dad.gr = b.gr;
        dad.sum = a.sum + b.sum -(a.gr+b.gl) + max(a.gr, b.gl);
    }
    return dad;
}
void add(int id, int val){
    st[id].mn += val;
    st[id].acum += val;
}

void update(int id, int l, int r, int x, int y, int val, int t){
    if(l > y || r < x) return;
    else if( x <= l && r <= y)  {
        if(t == 1) add(id, val);
        else st[id].freq = st[id].sum = val;
    }else{
        int mid = (l+r)/2;
        add(2*id, st[id].acum);      //LAZY
        add(2*id+1, st[id].acum);   // LAZY
        st[id].acum = 0;           //  LAZY

        update(2*id, l, mid, x, y, val, t);
        update(2*id+1, mid+1, r, x, y, val, t);

        st[id] = unhonho(st[2*id], st[2*id+1]);
    }
}

int a[MAX], n;
set<int> gp[MAX];
void rmv(int actual){
    if(!gp[actual].empty()){
        int l = *gp[actual].begin();
        int r = *gp[actual].rbegin();
        update(1, 1, n, l, r-1, -1, 1);
        update(1, 1, n, l, l, 0, 2);
    }
}

void add(int actual){
    if(!gp[actual].empty()){
        int l = *gp[actual].begin();
        int r = *gp[actual].rbegin();
        int sz = gp[actual].size();
        update(1, 1, n, l, r-1, 1, 1);
        update(1, 1, n, l, l, sz, 2);
    }
}

int process(int pos, int v){
    rmv(a[pos]);
    gp[a[pos]].erase(pos);
    add(a[pos]);

    a[pos] = v;
    rmv(a[pos]);
    gp[a[pos]].insert(pos);
    add(a[pos]);

    return n-st[1].sum;
}

int main(){
    int q; scanf("%d %d", &n, &q);

    int bg = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        gp[a[i]].insert(i);
        bg = max(a[i], bg);
    }

    for(int i = 1; i <= bg; i++) add(i);

    printf("%d\n", n-st[1].sum);
    while(q--){
        int p, v; scanf("%d %d", &p, &v);
        printf("%d\n", process(p, v));
    }
    return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
#define pii pair<int,int>
using namespace std;
typedef long long ll;
#define rint register int
const int maxn=200007;
const int inf=(1LL<<29);
int read(){
    int x=0;int f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;c=getchar();
    }
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    x*=f;return x;
}
struct nd{
    int mx,lm,rm,mn,val;
    void print(){
        printf("mx:%d lm:%d rm:%d mn:%d val:%d\n",mx,lm,rm,mn,val);
    }
}seg[maxn];
nd mg(nd a,nd b){
    nd N;N.mx=max(a.mx,b.mx);
    if(a.mn<b.mn){
        N.lm=a.lm;
        N.rm=max(a.rm,b.mx);
        N.val=a.val;
        N.mn=a.mn;
    }
    else if(a.mn>b.mn){
        N.rm=b.rm;
        N.lm=max(b.lm,a.mx);
        N.mn=b.mn;
        N.val=b.val;
    }
    else{
        N.lm=a.lm;
        N.rm=b.rm;
        N.mn=a.mn;
        N.val=a.val+b.val+max(a.rm,b.lm);
    }
    return N;
}
void pul(int o){
    seg[o]=mg(seg[o<<1],seg[o<<1|1]);
}
int tag[maxn<<2];
void pus(int o){
    tag[o<<1]+=tag[o];
    seg[o<<1].mn+=tag[o];
    tag[o<<1|1]+=tag[o];
    seg[o<<1|1].mn+=tag[o];
    tag[o]=0;
}
void upd(int o,int l,int r,int ql,int qr,int x){
   // printf("%d %d %d\n",o,l,r);
    if(l==ql&&r==qr){
        tag[o]+=x;seg[o].mn+=x;return;
    }
    pus(o);
    int m=(l+r)>>1;
    if(ql<=m&&qr>m) upd(o<<1,l,m,ql,m,x),upd(o<<1|1,m+1,r,m+1,qr,x);
    else if(ql<=m) upd(o<<1,l,m,ql,qr,x);
    else upd(o<<1|1,m+1,r,ql,qr,x);
    pul(o);
}
int you[maxn],a[maxn],n;set<int> pos[maxn];
void build(int o,int l,int r){
    if(l==r){
        if(*pos[a[l]].begin()==l) seg[o].mx=you[a[l]];
        seg[o].lm=seg[o].mx;
        return;
    }
    int m=(l+r)>>1;
    build(o<<1,l,m);build(o<<1|1,m+1,r);
    pul(o);
}
void ins(int x,int y){
    if(pos[a[x]].size()>1){
        if(x==*pos[a[x]].begin()){
            auto it=pos[a[x]].begin();it++;upd(1,1,n,x,(*it)-1,y);
        }
        else if(x==*pos[a[x]].rbegin()){
            auto it=pos[a[x]].rbegin();it++;
            upd(1,1,n,(*it),x-1,y);
        }
    }
}
void modify(int o,int l,int r,int x,int y){
    if(l==r){
        seg[o].lm=seg[o].mx=y;
        return;
    }
    pus(o);
    int m=(l+r)>>1;
    x<=m?modify(o<<1,l,m,x,y):modify(o<<1|1,m+1,r,x,y);
    pul(o);
}
nd query(int o,int l,int r,int ql,int qr){
    if(l==ql&&r==qr){
        return seg[o];
    }
    pus(o);
    int m=(l+r)>>1;
    if(ql<=m&&qr>m) return mg(query(o<<1,l,m,ql,m),query(o<<1|1,m+1,r,m+1,qr));
    else if(ql<=m) return query(o<<1,l,m,ql,qr);
    else return query(o<<1|1,m+1,r,ql,qr);
}
int main(){
  //  cin.tie(0);ios_base::sync_with_stdio(false);
    n=read();int m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();you[a[i]]++;
        pos[a[i]].insert(i);
    }
    build(1,1,n);
    for(int i=1;i<=200000;i++){
        if(pos[i].size()>1) upd(1,1,n,*pos[i].begin(),*pos[i].rbegin()-1,1);
    }
    printf("%d\n",n-(seg[1].val+seg[1].lm+seg[1].rm));
    for(int i=1;i<=m;i++){
        int x=read(),v=read();
        ins(x,-1);
        if(x==*pos[a[x]].begin()) modify(1,1,n,x,0);
        pos[a[x]].erase(x);
        if(pos[a[x]].size()) modify(1,1,n,*pos[a[x]].begin(),pos[a[x]].size());
        a[x]=v;
        if(pos[a[x]].size()) modify(1,1,n,*pos[a[x]].begin(),0);
        pos[v].insert(x);
        modify(1,1,n,*pos[a[x]].begin(),pos[a[x]].size());
        ins(x,1);
        printf("%d\n",n-seg[1].val-seg[1].lm-seg[1].rm);
     //   query(1,1,n,1,4).print();
    }
    return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
#define pii pair<int,int>
using namespace std;
typedef long long ll;
#define rint register int
const int maxn=200007;
const int inf=(1LL<<29);
int read(){
    int x=0;int f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;c=getchar();
    }
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    x*=f;return x;
}
struct nd{
    int mx,lm,rm,mn,val;
    void print(){
        printf("mx:%d lm:%d rm:%d mn:%d val:%d\n",mx,lm,rm,mn,val);
    }
}seg[maxn<<2];
nd mg(nd a,nd b){
    nd N;N.mx=max(a.mx,b.mx);
    if(a.mn<b.mn){
        N.lm=a.lm;
        N.rm=max(a.rm,b.mx);
        N.val=a.val;
        N.mn=a.mn;
    }
    else if(a.mn>b.mn){
        N.rm=b.rm;
        N.lm=max(b.lm,a.mx);
        N.mn=b.mn;
        N.val=b.val;
    }
    else{
        N.lm=a.lm;
        N.rm=b.rm;
        N.mn=a.mn;
        N.val=a.val+b.val+max(a.rm,b.lm);
    }
    return N;
}
void pul(int o){
    seg[o]=mg(seg[o<<1],seg[o<<1|1]);
}
int tag[maxn<<2];
void pus(int o){
    tag[o<<1]+=tag[o];
    seg[o<<1].mn+=tag[o];
    tag[o<<1|1]+=tag[o];
    seg[o<<1|1].mn+=tag[o];
    tag[o]=0;
}
void upd(int o,int l,int r,int ql,int qr,int x){
   // printf("%d %d %d\n",o,l,r);
    if(l==ql&&r==qr){
        tag[o]+=x;seg[o].mn+=x;return;
    }
    pus(o);
    int m=(l+r)>>1;
    if(ql<=m&&qr>m) upd(o<<1,l,m,ql,m,x),upd(o<<1|1,m+1,r,m+1,qr,x);
    else if(ql<=m) upd(o<<1,l,m,ql,qr,x);
    else upd(o<<1|1,m+1,r,ql,qr,x);
    pul(o);
}
int you[maxn],a[maxn],n;set<int> pos[maxn];
void build(int o,int l,int r){
    if(l==r){
        if(*pos[a[l]].begin()==l) seg[o].mx=you[a[l]];
        seg[o].lm=seg[o].mx;
        return;
    }
    int m=(l+r)>>1;
    build(o<<1,l,m);build(o<<1|1,m+1,r);
    pul(o);
}
void ins(int x,int y){
    if(pos[a[x]].size()>1){
        if(x==*pos[a[x]].begin()){
            auto it=pos[a[x]].begin();it++;upd(1,1,n,x,(*it)-1,y);
        }
        else if(x==*pos[a[x]].rbegin()){
            auto it=pos[a[x]].rbegin();it++;
            upd(1,1,n,(*it),x-1,y);
        }
    }
}
void modify(int o,int l,int r,int x,int y){
    if(l==r){
        seg[o].lm=seg[o].mx=y;
        return;
    }
    pus(o);
    int m=(l+r)>>1;
    x<=m?modify(o<<1,l,m,x,y):modify(o<<1|1,m+1,r,x,y);
    pul(o);
}
nd query(int o,int l,int r,int ql,int qr){
    if(l==ql&&r==qr){
        return seg[o];
    }
    pus(o);
    int m=(l+r)>>1;
    if(ql<=m&&qr>m) return mg(query(o<<1,l,m,ql,m),query(o<<1|1,m+1,r,m+1,qr));
    else if(ql<=m) return query(o<<1,l,m,ql,qr);
    else return query(o<<1|1,m+1,r,ql,qr);
}
int main(){
  //  cin.tie(0);ios_base::sync_with_stdio(false);
    n=read();int m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();you[a[i]]++;
        pos[a[i]].insert(i);
    }
    build(1,1,n);
    for(int i=1;i<=200000;i++){
        if(pos[i].size()>1) upd(1,1,n,*pos[i].begin(),*pos[i].rbegin()-1,1);
    }
    printf("%d\n",n-(seg[1].val+seg[1].lm+seg[1].rm));
    for(int i=1;i<=m;i++){
        int x=read(),v=read();
        ins(x,-1);
        if(x==*pos[a[x]].begin()) modify(1,1,n,x,0);
        pos[a[x]].erase(x);
        if(pos[a[x]].size()) modify(1,1,n,*pos[a[x]].begin(),pos[a[x]].size());
        a[x]=v;
        if(pos[a[x]].size()) modify(1,1,n,*pos[a[x]].begin(),0);
        pos[v].insert(x);
        modify(1,1,n,*pos[a[x]].begin(),pos[a[x]].size());
        ins(x,1);
        printf("%d\n",n-seg[1].val-seg[1].lm-seg[1].rm);
     //   query(1,1,n,1,4).print();
    }
    return 0;
}


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

#ifndef LOCAL
		#define eprintf(...) fprintf(stderr, _VA_ARGS_)
#else
		#define eprintf(...) 42
#endif

typedef long long LL;
const int N = 2e5 + 10;

template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x) {
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}

int n , q , bound;
int a[N];
set< int > st[N];

struct info {
		int Min , l , r , sum;
} ;

struct RMQ_Segment_Tree {
	 struct node {
	 		int lc , rc;
	 		int Max;
	 } a[N << 2];
	 int n , root , size;
	 inline void upd(int root) {
	 		a[root].Max = max(a[a[root].lc].Max , a[a[root].rc].Max);
	 }
	 inline void build(int &root , int l , int r) {
	 		if (!root) root = ++size;
	 		a[root].Max = 0;
	 		if (l == r) return;
	 		int mid = l + r >> 1;
	 		build(a[root].lc , l , mid);
	 		build(a[root].rc , mid + 1 , r);
	 }
	 inline void init(int x) {
	 		n = x;
	 		root = size = 0;
	 		build(root , 0 , n);
	 }
	 inline void modify(int root , int l , int r , int x , int val) {
	 		if (l == r) {
	 				a[root].Max = val;
	 				return;
			}
			int mid = l + r >> 1;
			if (mid >= x) modify(a[root].lc , l , mid , x , val);
			else modify(a[root].rc , mid + 1 , r , x , val);
			upd(root);
	 }
	 inline void modify(int pos , int val) {
	 		modify(root , 0 , n , pos , val);
	 }
	 inline int query(int root , int l , int r , int ql , int qr) {
	 		if (l == ql && r == qr)
	 				return a[root].Max;
	 		int mid = l + r >> 1;
	 		if (mid >= qr) return query(a[root].lc , l , mid , ql , qr);
	 		else if (mid + 1 <= ql) return query(a[root].rc , mid + 1 , r , ql , qr);
	 		else return max(query(a[root].lc , l , mid , ql , mid) , query(a[root].rc , mid + 1 , r , mid + 1 , qr));
	 }
	 inline int query(int l , int r) {
	 		return query(root , 0 , n , l , r);
	 }
} STM;

info operator + (info a , info b) {
		if (a.Min < b.Min) return a;
		if (a.Min > b.Min) return b;
		info ret; ret.Min = a.Min;
		ret.l = a.l; ret.r = b.r;
		ret.sum = a.sum + b.sum + STM.query(a.r + 1 , b.l);
		return ret;
}

struct Main_Segment_Tree {
		struct node {
				int lc , rc , tag;
				info ans;
		} a[N << 2];
		int n , root , size;
		inline void upd(int x) {
				a[x].ans = a[a[x].lc].ans + a[a[x].rc].ans;
		}
		inline void build(int &root , int l , int r) {
				if (!root) root = ++size;
				if (l == r) {
						a[root].ans = (info){0 , l , l , 0};
						return;
				}
				int mid = l + r >> 1;
				build(a[root].lc , l , mid);
				build(a[root].rc , mid + 1 , r);
				upd(root);
		}
		inline void init(int x) {
				n = x;
				root = size = 0;
				build(root , 0 , n);
		}
		inline void pushdown(int x) {
				if (a[x].tag) {
						a[a[x].lc].tag += a[x].tag;
						a[a[x].rc].tag += a[x].tag;
						a[a[x].lc].ans.Min += a[x].tag;
						a[a[x].rc].ans.Min += a[x].tag;
						a[x].tag = 0;
				}
				return;
		}
		inline void modify(int root , int l , int r , int x , int val) {
				if (l == r) {
						STM.modify(x , val);
						return;
				}
				pushdown(root);
				int mid = l + r >> 1;
				if (mid >= x) modify(a[root].lc , l , mid , x , val);
				else modify(a[root].rc , mid + 1 , r , x , val);
				upd(root);
		}
		inline void modify(int pos , int val) {
				modify(root , 0 , n , pos , val);
		}
		inline void modify(int root , int l , int r , int ql , int qr , int val) {
				if (ql > qr) return;
				if (l == ql && r == qr) {
						a[root].tag += val;
						a[root].ans.Min += val;
						return;
				}
				pushdown(root);
				int mid = l + r >> 1;
				if (mid >= qr) modify(a[root].lc , l , mid , ql , qr , val);
				else if (mid + 1 <= ql) modify(a[root].rc , mid + 1 , r , ql , qr , val);
				else {
						modify(a[root].lc , l , mid , ql , mid , val);
						modify(a[root].rc , mid + 1 , r , mid + 1 , qr , val);
				}
				upd(root);
		}
		inline void modify(int l , int r , int val) {
				modify(root , 0 , n , l , r , val);
		}
} STA;

int main() {

		read(n); read(q);
		for (int i = 1; i <= n; ++i) {
				read(a[i]);
				chkmax(bound , a[i]);
				st[a[i]].insert(i);
		}
		STM.init(n);
		STA.init(n);
		for (int i = 1; i <= bound; ++i) {
				if (st[i].size()) {
						STA.modify(*st[i].begin() , st[i].size());
						if (st[i].size() >= 2) STA.modify(*st[i].begin() , *st[i].rbegin() - 1 , 1);
				}
		}
		printf("%d\n" , n - STA.a[STA.root].ans.sum);
		while (q--) {
				int x , v;
				read(x); read(v);
				STA.modify(*st[a[x]].begin() , 0);
				if (st[a[x]].size() >= 2) STA.modify(*st[a[x]].begin() , *st[a[x]].rbegin() - 1 , -1);
				st[a[x]].erase(x);
				if (st[a[x]].size()) {
						STA.modify(*st[a[x]].begin() , st[a[x]].size());
						if (st[a[x]].size() >= 2) STA.modify(*st[a[x]].begin() , *st[a[x]].rbegin() - 1 , 1);
				}
				a[x] = v;
				if (st[a[x]].size()) {
						STA.modify(*st[a[x]].begin() , 0);
						if (st[a[x]].size() >= 2) STA.modify(*st[a[x]].begin() , *st[a[x]].rbegin() - 1 , -1);
				}
				st[a[x]].insert(x);
				STA.modify(*st[a[x]].begin() , st[a[x]].size());
				if (st[a[x]].size() >= 2) STA.modify(*st[a[x]].begin() , *st[a[x]].rbegin() - 1 , 1);
				printf("%d\n" , n - STA.a[STA.root].ans.sum);
		}

	  return 0;

}


#include <bits/stdc++.h>
using namespace std;
#define N 1000010
struct no{
	int mn,l,r,mx,a,d;
}a[N];
set<int>s[N/5];
int n,q,x[N];
no operator +(no x,no y){
	no r;
	r.d=0;
	r.mx=max(x.mx,y.mx);
	r.mn=min(x.mn,y.mn);
	if(x.mn<y.mn){
		r.l=x.l;
		r.r=max(x.r,y.mx);
		r.a=x.a;
	}
	else if(x.mn>y.mn){
		r.l=max(x.mx,y.l);
		r.r=y.r;
		r.a=y.a;
	}
	else{
		r.l=x.l;
		r.r=y.r;
		r.a=x.a+y.a+max(x.r,y.l);
	}
	return r;
}
void pd(int o){
	int t=a[o].d;
	a[o*2].d+=t;
	a[o*2+1].d+=t;
	a[o*2].mn+=t;
	a[o*2+1].mn+=t;
	a[o].d=0;
}
void ad(int o,int l,int r,int x,int y,int v){
	if(r<x||y<l)return;
	if(x<=l&&r<=y){
		a[o].d+=v;
		a[o].mn+=v;
		return;
	}
	pd(o);
	int md=(l+r)/2;
	ad(o*2,l,md,x,y,v);
	ad(o*2+1,md+1,r,x,y,v);
	a[o]=a[o*2]+a[o*2+1];
}
void mod(int o,int l,int r,int x,int y){
	if(l==r){
		a[o].l=a[o].r=a[o].mx=y;
		return;
	}
	pd(o);
	int md=(l+r)/2;
	x<=md?mod(o*2,l,md,x,y):mod(o*2+1,md+1,r,x,y);
	a[o]=a[o*2]+a[o*2+1];
}
void cg(int v,int d){
	if(!s[v].empty()){
		if(s[v].size()>1)ad(1,0,n,*s[v].begin(),*s[v].rbegin()-1,d);
		mod(1,0,n,*s[v].begin(),(d==-1)?0:s[v].size());
	}
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++){
		scanf("%d",x+i);
		s[x[i]].insert(i);
	}
	for(int i=0;i<N/5;i++)cg(i,1);
	printf("%d\n",n-a[1].a);
	while(q--){
		int c,d;
		scanf("%d%d",&c,&d);
		cg(x[c],-1);
		s[x[c]].erase(c);
		cg(x[c],1);
		x[c]=d;
		cg(d,-1);
		s[d].insert(c);
		cg(d,1);
		printf("%d\n",n-a[1].a);
	}
}