/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
set <int> s[N];
int is(int i, int j) {
	return s[j].find(i) != s[j].end();
}
void solve() {
	int n, m, ans = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		int t;
		cin >> t;
		t--;
		s[t].insert(i);
	}
	for (int i = 0; i < n; i++) {
		for (auto u : s[i]) {
			if(u != n - 1)
				ans += !(is(u + 1, i));
		}
	}
	cout << ans << endl;
	for (int i = 0; i < m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		if(s[a].size() < s[b].size())
			swap(s[a], s[b]);
		for (auto u : s[b]) {
			if(is(u + 1, a))
				ans--;
			if(is(u - 1, a))
				ans--;
		}
		for (auto u : s[b])
			s[a].insert(u);
		cout << ans << endl;
	}
}

signed main() {
    fast
    solve();
}


/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

//#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
int t[N], p[N], tin[N], tout[N], up[N][lg];
int te =0;
vi v[N];
bool isanc(int a, int b) {
	return tin[a] <= tin[b] && tout[a] >= tout[b];
}
void dfs(int x, int pr) {
	if(pr != -1)
		up[x][0] = pr;
	tin[x] = te++;
	//cout << x << ' ';
	for (auto u : v[x]) {
		if(u != pr)
			dfs(u, x);
	}
	tout[x] = te++;
}
int lca(int a, int b) {
	if(isanc(a, b))
		return a;
	if(isanc(b, a))
		return b;
	for (int i = lg - 1; i >= 0; i--) {
		if(isanc(up[a][i], b))
			continue;
		a = up[a][i];
	}
	return up[a][0];
}
int add[N];
void solve() {
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> t[i];
		t[i]--;
	}
	iota(p, p + m, 0);
	for (int i = m; i < 2 * m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		v[i].pb(p[a]);
		v[i].pb(p[b]);
		p[a] = i;
		p[b] = i;
	}
	up[2 * m - 2][0] = 2 * m - 2;
	dfs(2 * m - 2, -1);
	//cout << endl;
	for (int k = 1; k < lg; k++) {
		for (int i = 0; i <= 2 * m - 2; i++)
			up[i][k] = up[up[i][k - 1]][k - 1];
	}
	int sum = n - 1;
	for (int i = 0; i < n - 1; i++) {
		int c = lca(t[i], t[i + 1]);
		if(c < m)
			sum--;
		else
			add[c - m]--;
	}
	for (int i = 0; i < m; i++) {
		cout << sum << endl;
		sum += add[i];
	}
}

signed main() {
    fast
    solve();
}


/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

//#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
int t[N], p[N], tin[N], tout[N], up[N][lg];
int te =0;
vi v[N];
bool isanc(int a, int b) {
	return tin[a] <= tin[b] && tout[a] >= tout[b];
}
void dfs(int x, int pr) {
	if(pr != -1)
		up[x][0] = pr;
	tin[x] = te++;
	//cout << x << ' ';
	for (auto u : v[x]) {
		if(u != pr)
			dfs(u, x);
	}
	tout[x] = te++;
}
int lca(int a, int b) {
	if(isanc(a, b))
		return a;
	if(isanc(b, a))
		return b;
	for (int i = lg - 1; i >= 0; i--) {
		if(isanc(up[a][i], b))
			continue;
		a = up[a][i];
	}
	return up[a][0];
}
int add[N];
void solve() {
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> t[i];
		t[i]--;
	}
	iota(p, p + m, 0);
	for (int i = m; i < 2 * m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		v[i].pb(p[a]);
		v[i].pb(p[b]);
		p[a] = i;
		p[b] = i;
	}
	up[2 * m - 2][0] = 2 * m - 2;
	dfs(2 * m - 2, -1);
	//cout << endl;
	for (int k = 1; k < lg; k++) {
		for (int i = 0; i < n; i++)
			up[i][k] = up[up[i][k - 1]][k - 1];
	}
	int sum = n - 1;
	for (int i = 0; i < n - 1; i++) {
		int c = lca(t[i], t[i + 1]);
		if(c < m)
			sum--;
		else
			add[c - m]--;
	}
	for (int i = 0; i < m; i++) {
		cout << sum << endl;
		sum += add[i];
	}
}

signed main() {
    fast
    solve();
}


/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
set <int> s[N];
int is(int i, int j) {
	return s[j].find(i) != s[j].end();
}
void solve() {
	int n, m, ans = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		int t;
		cin >> t;
		t--;
		s[t].insert(i);
	}
	for (int i = 0; i < n; i++) {
		for (auto u : s[i]) {
			if(u != n - 1)
				ans += !(is(u + 1, i));
		}
	}
	cout << ans << endl;
	for (int i = 0; i < m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		if(rnd() % 2)
			swap(s[a], s[b]);
		for (auto u : s[b]) {
			if(is(u + 1, a))
				ans--;
			if(is(u - 1, a))
				ans--;
		}
		for (auto u : s[b])
			s[a].insert(u);
		cout << ans << endl;
	}
}

signed main() {
    fast
    solve();
}


/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
set <int> s[N];
int is(int i, int j) {
	return s[j].find(i) != s[j].end();
}
void solve() {
	int n, m, ans = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		int t;
		cin >> t;
		t--;
		s[t].insert(i);
	}
	for (int i = 0; i < n; i++) {
		for (auto u : s[i]) {
			if(u != n - 1)
				ans += !(is(u + 1, i));
		}
	}
	cout << ans << endl;
	for (int i = 0; i < m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		for (auto u : s[b]) {
			if(is(u + 1, a))
				ans--;
			if(is(u - 1, a))
				ans--;
		}
		for (auto u : s[b])
			s[a].insert(u);
		cout << ans << endl;
	}
}

signed main() {
    fast
    solve();
}


/* ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄            ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄         ▄       ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌          ▐░▌          ▐░░░░░░░░░░░▌▐░▌       ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░▌          ▐░█▀▀▀▀▀▀▀█░▌▐░▌       ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌     ▐░▌          ▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌   ▄   ▐░▌     ▐░▌ ▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌▐░▌       ▐░▌
▐░░░░░░░░░░░▌▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌  ▐░▌  ▐░▌     ▐░▌▐░░░░░░░░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌ ▐░▌░▌ ▐░▌     ▐░▌ ▀▀▀▀▀▀█░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░▌       ▐░▌▐░▌          ▐░▌          ▐░▌       ▐░▌▐░▌▐░▌ ▐░▌▐░▌     ▐░▌       ▐░▌▐░▌       ▐░▌▐░▌       ▐░▌
▐░▌          ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░▌░▌   ▐░▐░▌     ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌
▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌     ▐░░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌
 ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀       ▀▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  */

//#pragma optimization_level 3

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <chrono>
#include <ctime>
#include <queue>
#include <math.h>
#include <deque>
#include <stack>
#include <iomanip>
#include <assert.h>
#include <stdio.h>
#include <cstring>
#include <random>

using namespace std;

//#define int long long
#define ld long double
#define ull unsigned long long
#define endl '\n'
#define try tr
#define pii pair<int, int>
#define ti tuple <int, int, int>
#define vi vector <int>
#define vpi vector <pii>
#define umap unordered_map
#define uset unordered_set
#define left left11
#define right right11
#define all(c) (c).begin(), (c).end()
#define pb push_back
#define sqr(a) ((a) * (a))
#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

#define X first
#define Y second

ld TL = 1.0;
bool is_tl = 0;
int CALLS = 0;

inline bool IS() {
    if (++CALLS == 1000) {
        CALLS = 0;
        is_tl |= clock() > (TL - 0.1) * CLOCKS_PER_SEC;
    }
    return is_tl;
}

template<typename T1, typename T2>
inline void amin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void amax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> &p) {
    os << p.first << ' ' << p.second << endl;
    return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &v) {
    for (auto &u : v) os << u << ' ';
    os << endl;
    return os;
}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1e6 + 7, NS = 2e3 + 7, lg = 19, sq = 550, inf = 2e9 + 7, SM = 1e2 + 7;
const ld eps = 1e-9;
int hash_mod[4] = {1000000007, 998244353, 1000000009, 999999937}, mod = hash_mod[rnd() % 4];
int hash_pows[4] = {179, 239, 1007, 2003}, P = hash_pows[rnd() % 4];
set <int> s[N];
int is(int i, int j) {
	return s[j].find(i) != s[j].end();
}
void solve() {
	int n, m, ans = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		int t;
		cin >> t;
		t--;
		s[t].insert(i);
	}
	for (int i = 0; i < n; i++) {
		for (auto u : s[i]) {
			if(u != n - 1)
				ans += !(is(u + 1, i));
		}
	}
	cout << ans << endl;
	for (int i = 0; i < m - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		for (auto u : s[b]) {
			if(is(u + 1, a))
				ans--;
			if(is(u - 1, a))
				ans--;
		}
		for (auto u : s[b])
			s[a].insert(u);
		cout << ans << endl;
	}
}

signed main() {
    fast
    solve();
}


// ./e-merging-towers.yml
#include "bits/stdc++.h"
using namespace std;

// Defines
#define fs first
#define sn second
#define pb push_back
#define eb emplace_back
#define mpr make_pair
#define mtp make_tuple
#define all(x) (x).begin(), (x).end()
// Basic type definitions
using ll = long long; using ull = unsigned long long; using ld = long double;
using pii = pair<int, int>; using pll = pair<long long, long long>;
// PBDS order statistic tree
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T, class comp = less<T>> using os_tree = tree<T, null_type, comp, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V, class comp = less<K>> using treemap = tree<K, V, comp, rb_tree_tag, tree_order_statistics_node_update>;
// HashSet
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
const ll RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash { ll operator()(ll x) const { return x ^ RANDOM; } };
template <typename T, class Hash> using hashset = gp_hash_table<T, null_type, Hash>;
template <typename K, typename V, class Hash> using hashmap = gp_hash_table<K, V, Hash>;
// More utilities
int SZ(string &v) { return v.length(); }
template <typename C> int SZ(C &v) { return v.size(); }
template <typename T, typename U> void maxa(T &a, U b) { a = max(a, b); }
template <typename T, typename U> void mina(T &a, U b) { a = min(a, b); }
const ll INF = 0x3f3f3f3f, LLINF = 0x3f3f3f3f3f3f3f3f;

struct Seg {
    int l, r, x;
    bool operator<(const Seg &o) const {
        return l == o.l ? x < o.x : l < o.l;
    }
};

ostream& operator<<(ostream& out, const Seg o) {
    out << "(l=" << o.l << ", r=" << o.r << ", x=" << o.x << ")";
    return out;
}

const int MN = 2e5 + 10;
int N, M,
    val[MN];
set<Seg> segs;

struct DSU {
    vector<int> dsu;
    vector<set<int>> ind;
    void init(int N) {
        dsu.resize(N + 1);
        ind.resize(N + 1);
        iota(dsu.begin(), dsu.end(), 0);
    }
    int rt(int x) { return dsu[x] == x ? x : dsu[x] = rt(dsu[x]); }
    void merge(int x, int y) { // x -> y
        int rx = rt(x), ry = rt(y);
        if (SZ(ind[ry]) > SZ(ind[rx])) ind[rx].swap(ind[ry]);
        ind[ry].insert(all(ind[rx]));
        dsu[rx] = ry;
    }
    set<int>& gind(int x) { return ind[rt(x)]; }
    bool same(int a, int b) {
        if (a == -1 || b == -1) return false;
        return rt(a) == rt(b);
    }
};

DSU dsu;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> (N) >> (M);
    for (auto i = 1; i <= N; i++)
        cin >> (val[i]);

    segs.insert({-INF, -1, -1});
    segs.insert({INF, -1, -1});
    dsu.init(N);
    int pre = 1;
    for (auto i = 1; i <= N; i++) {
        if (val[i] != val[pre]) {
            segs.insert({pre, i - 1, val[pre]});
            dsu.ind[val[pre]].insert(pre);
            pre = i;
        }
    }
    segs.insert({pre, N, val[pre]});
    dsu.ind[val[pre]].insert(pre);

    cout << (SZ(segs)-3) << '\n';
    for (auto i = 1; i < M; i++) {
        int a, b;
        cin >> a >> b;

        // cout<<"a="<<(a)<<", "; cout<<"b="<<(b)<<", "; cout << "segs=["; for (auto x:segs)cout<<x<<", "; cout<<"], "; cout << endl; // db a,b,I:segs

        int oa = a, ob = b;
        if (SZ(dsu.gind(a)) < SZ(dsu.gind(b))) swap(a, b);
        auto oi = dsu.gind(b);
        dsu.merge(ob, oa);
        for (auto x : oi) {
            auto pre = segs.lower_bound({x, -1, -1}), ptr = pre, nxt = pre; pre--; nxt++;
            // cout<<"*pre="<<(*pre)<<", "; cout<<"*ptr="<<(*ptr)<<", "; cout<<"*nxt="<<(*nxt)<<", "; cout << endl; // db *pre,*ptr,*nxt
            Seg nv{ptr->l, ptr->r, ptr->x};
            if (dsu.same(pre->x, a)) {
                nv.l = pre->l;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"pre->l="<<(pre->l)<<", "; cout << endl; // db I:dsu.gind(a),pre->l
                dsu.gind(a).erase(pre->l);
                segs.erase(pre);
            }
            if (dsu.same(nxt->x, a)) {
                nv.r = nxt->r;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"nxt->l="<<(nxt->l)<<", "; cout << endl; // db I:dsu.gind(a),nxt->l
                dsu.gind(a).erase(nxt->l);
                segs.erase(nxt);
            }
            // cout << "dsu.gind(b)=["; for (auto x:dsu.gind(b))cout<<x<<", "; cout<<"], "; cout<<"ptr->l="<<(ptr->l)<<", "; cout << endl; // db I:dsu.gind(b),ptr->l
            dsu.gind(b).erase(ptr->l);
            segs.erase(ptr);
            segs.insert(nv);
            dsu.gind(b).insert(nv.l);
        }

        cout << (SZ(segs)-3) << '\n';
    }

    return 0;
}


// ./e-merging-towers.yml
#include "bits/stdc++.h"
using namespace std;

// Defines
#define fs first
#define sn second
#define pb push_back
#define eb emplace_back
#define mpr make_pair
#define mtp make_tuple
#define all(x) (x).begin(), (x).end()
// Basic type definitions
using ll = long long; using ull = unsigned long long; using ld = long double;
using pii = pair<int, int>; using pll = pair<long long, long long>;
// PBDS order statistic tree
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T, class comp = less<T>> using os_tree = tree<T, null_type, comp, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V, class comp = less<K>> using treemap = tree<K, V, comp, rb_tree_tag, tree_order_statistics_node_update>;
// HashSet
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
const ll RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash { ll operator()(ll x) const { return x ^ RANDOM; } };
template <typename T, class Hash> using hashset = gp_hash_table<T, null_type, Hash>;
template <typename K, typename V, class Hash> using hashmap = gp_hash_table<K, V, Hash>;
// More utilities
int SZ(string &v) { return v.length(); }
template <typename C> int SZ(C &v) { return v.size(); }
template <typename T, typename U> void maxa(T &a, U b) { a = max(a, b); }
template <typename T, typename U> void mina(T &a, U b) { a = min(a, b); }
const ll INF = 0x3f3f3f3f, LLINF = 0x3f3f3f3f3f3f3f3f;

struct Seg {
    int l, r, x;
    bool operator<(const Seg &o) const {
        return l == o.l ? x < o.x : l < o.l;
    }
};

ostream& operator<<(ostream& out, const Seg o) {
    out << "(l=" << o.l << ", r=" << o.r << ", x=" << o.x << ")";
    return out;
}

const int MN = 2e5 + 10;
int N, M,
    val[MN];
set<Seg> segs;

struct DSU {
    vector<int> dsu;
    vector<unordered_set<int>> ind;
    void init(int N) {
        dsu.resize(N + 1);
        ind.resize(N + 1);
        iota(dsu.begin(), dsu.end(), 0);
    }
    int rt(int x) { return dsu[x] == x ? x : dsu[x] = rt(dsu[x]); }
    void merge(int x, int y) { // x -> y
        int rx = rt(x), ry = rt(y);
        if (SZ(ind[ry]) < SZ(ind[rx])) ind[rx].swap(ind[ry]);
        ind[ry].insert(all(ind[rx]));
        ind[rx].clear();
        dsu[rx] = ry;
    }
    unordered_set<int>& gind(int x) { return ind[rt(x)]; }
    bool same(int a, int b) {
        if (a == -1 || b == -1) return false;
        return rt(a) == rt(b);
    }
};

DSU dsu;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> (N) >> (M);
    for (auto i = 1; i <= N; i++)
        cin >> (val[i]);

    segs.insert({-INF, -1, -1});
    segs.insert({INF, -1, -1});
    dsu.init(N);
    int pre = 1;
    for (auto i = 1; i <= N; i++) {
        if (val[i] != val[pre]) {
            segs.insert({pre, i - 1, val[pre]});
            dsu.ind[val[pre]].insert(pre);
            pre = i;
        }
    }
    segs.insert({pre, N, val[pre]});
    dsu.ind[val[pre]].insert(pre);

    cout << (SZ(segs)-3) << '\n';
    for (auto i = 1; i < M; i++) {
        int a, b;
        cin >> a >> b;

        // cout<<"a="<<(a)<<", "; cout<<"b="<<(b)<<", "; cout << "segs=["; for (auto x:segs)cout<<x<<", "; cout<<"], "; cout << endl; // db a,b,I:segs

        int oa = a, ob = b;
        if (SZ(dsu.gind(a)) < SZ(dsu.gind(b))) swap(a, b);
        auto oi = dsu.gind(b);
        dsu.merge(ob, oa);
        for (auto x : oi) {
            auto pre = segs.lower_bound({x, -1, -1}), ptr = pre, nxt = pre; pre--; nxt++;
            // cout<<"*pre="<<(*pre)<<", "; cout<<"*ptr="<<(*ptr)<<", "; cout<<"*nxt="<<(*nxt)<<", "; cout << endl; // db *pre,*ptr,*nxt
            Seg nv{ptr->l, ptr->r, ptr->x};
            if (dsu.same(pre->x, a)) {
                nv.l = pre->l;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"pre->l="<<(pre->l)<<", "; cout << endl; // db I:dsu.gind(a),pre->l
                dsu.gind(a).erase(pre->l);
                segs.erase(pre);
            }
            if (dsu.same(nxt->x, a)) {
                nv.r = nxt->r;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"nxt->l="<<(nxt->l)<<", "; cout << endl; // db I:dsu.gind(a),nxt->l
                dsu.gind(a).erase(nxt->l);
                segs.erase(nxt);
            }
            // cout << "dsu.gind(b)=["; for (auto x:dsu.gind(b))cout<<x<<", "; cout<<"], "; cout<<"ptr->l="<<(ptr->l)<<", "; cout << endl; // db I:dsu.gind(b),ptr->l
            dsu.gind(b).erase(ptr->l);
            segs.erase(ptr);
            segs.insert(nv);
            dsu.gind(b).insert(nv.l);
        }

        cout << (SZ(segs)-3) << '\n';
    }

    return 0;
}


// ./e-merging-towers.yml
#include "bits/stdc++.h"
using namespace std;

// Defines
#define fs first
#define sn second
#define pb push_back
#define eb emplace_back
#define mpr make_pair
#define mtp make_tuple
#define all(x) (x).begin(), (x).end()
// Basic type definitions
using ll = long long; using ull = unsigned long long; using ld = long double;
using pii = pair<int, int>; using pll = pair<long long, long long>;
// PBDS order statistic tree
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T, class comp = less<T>> using os_tree = tree<T, null_type, comp, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V, class comp = less<K>> using treemap = tree<K, V, comp, rb_tree_tag, tree_order_statistics_node_update>;
// HashSet
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
const ll RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash { ll operator()(ll x) const { return x ^ RANDOM; } };
template <typename T, class Hash> using hashset = gp_hash_table<T, null_type, Hash>;
template <typename K, typename V, class Hash> using hashmap = gp_hash_table<K, V, Hash>;
// More utilities
int SZ(string &v) { return v.length(); }
template <typename C> int SZ(C &v) { return v.size(); }
template <typename T, typename U> void maxa(T &a, U b) { a = max(a, b); }
template <typename T, typename U> void mina(T &a, U b) { a = min(a, b); }
const ll INF = 0x3f3f3f3f, LLINF = 0x3f3f3f3f3f3f3f3f;

struct Seg {
    int l, r, x;
    bool operator<(const Seg &o) const {
        return l == o.l ? x < o.x : l < o.l;
    }
};

ostream& operator<<(ostream& out, const Seg o) {
    out << "(l=" << o.l << ", r=" << o.r << ", x=" << o.x << ")";
    return out;
}

const int MN = 2e5 + 10;
int N, M,
    val[MN];
set<Seg> segs;

struct DSU {
    vector<int> dsu;
    vector<set<int>> ind;
    void init(int N) {
        dsu.resize(N + 1);
        ind.resize(N + 1);
        iota(dsu.begin(), dsu.end(), 0);
    }
    int rt(int x) { return dsu[x] == x ? x : dsu[x] = rt(dsu[x]); }
    void merge(int x, int y) { // x -> y
        int rx = rt(x), ry = rt(y);
        if (SZ(ind[ry]) < SZ(ind[rx])) ind[rx].swap(ind[ry]);
        ind[ry].insert(all(ind[rx]));
        ind[rx].clear();
        dsu[rx] = ry;
    }
    set<int>& gind(int x) { return ind[rt(x)]; }
    bool same(int a, int b) {
        if (a == -1 || b == -1) return false;
        return rt(a) == rt(b);
    }
};

DSU dsu;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> (N) >> (M);
    for (auto i = 1; i <= N; i++)
        cin >> (val[i]);

    segs.insert({-INF, -1, -1});
    segs.insert({INF, -1, -1});
    dsu.init(N);
    int pre = 1;
    for (auto i = 1; i <= N; i++) {
        if (val[i] != val[pre]) {
            segs.insert({pre, i - 1, val[pre]});
            dsu.ind[val[pre]].insert(pre);
            pre = i;
        }
    }
    segs.insert({pre, N, val[pre]});
    dsu.ind[val[pre]].insert(pre);

    cout << (SZ(segs)-3) << '\n';
    for (auto i = 1; i < M; i++) {
        int a, b;
        cin >> a >> b;

        // cout<<"a="<<(a)<<", "; cout<<"b="<<(b)<<", "; cout << "segs=["; for (auto x:segs)cout<<x<<", "; cout<<"], "; cout << endl; // db a,b,I:segs

        int oa = a, ob = b;
        if (SZ(dsu.gind(a)) < SZ(dsu.gind(b))) swap(a, b);
        auto oi = dsu.gind(b);
        dsu.merge(ob, oa);
        for (auto x : oi) {
            auto pre = segs.lower_bound({x, -1, -1}), ptr = pre, nxt = pre; pre--; nxt++;
            // cout<<"*pre="<<(*pre)<<", "; cout<<"*ptr="<<(*ptr)<<", "; cout<<"*nxt="<<(*nxt)<<", "; cout << endl; // db *pre,*ptr,*nxt
            Seg nv{ptr->l, ptr->r, ptr->x};
            if (dsu.same(pre->x, a)) {
                nv.l = pre->l;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"pre->l="<<(pre->l)<<", "; cout << endl; // db I:dsu.gind(a),pre->l
                dsu.gind(a).erase(pre->l);
                segs.erase(pre);
            }
            if (dsu.same(nxt->x, a)) {
                nv.r = nxt->r;
                // cout << "dsu.gind(a)=["; for (auto x:dsu.gind(a))cout<<x<<", "; cout<<"], "; cout<<"nxt->l="<<(nxt->l)<<", "; cout << endl; // db I:dsu.gind(a),nxt->l
                dsu.gind(a).erase(nxt->l);
                segs.erase(nxt);
            }
            // cout << "dsu.gind(b)=["; for (auto x:dsu.gind(b))cout<<x<<", "; cout<<"], "; cout<<"ptr->l="<<(ptr->l)<<", "; cout << endl; // db I:dsu.gind(b),ptr->l
            dsu.gind(b).erase(ptr->l);
            segs.erase(ptr);
            segs.insert(nv);
            dsu.gind(b).insert(nv.l);
        }

        cout << (SZ(segs)-3) << '\n';
    }

    return 0;
}


// ./e-merging-towers.yml
#include "bits/stdc++.h"
using namespace std;

// Defines
#define fs first
#define sn second
#define pb push_back
#define eb emplace_back
#define mpr make_pair
#define mtp make_tuple
#define all(x) (x).begin(), (x).end()
// Basic type definitions
using ll = long long; using ull = unsigned long long; using ld = long double;
using pii = pair<int, int>; using pll = pair<long long, long long>;
// PBDS order statistic tree
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T, class comp = less<T>> using os_tree = tree<T, null_type, comp, rb_tree_tag, tree_order_statistics_node_update>;
template <typename K, typename V, class comp = less<K>> using treemap = tree<K, V, comp, rb_tree_tag, tree_order_statistics_node_update>;
// HashSet
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
const ll RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash { ll operator()(ll x) const { return x ^ RANDOM; } };
template <typename T, class Hash> using hashset = gp_hash_table<T, null_type, Hash>;
template <typename K, typename V, class Hash> using hashmap = gp_hash_table<K, V, Hash>;
// More utilities
int SZ(string &v) { return v.length(); }
template <typename C> int SZ(C &v) { return v.size(); }
template <typename T, typename U> void maxa(T &a, U b) { a = max(a, b); }
template <typename T, typename U> void mina(T &a, U b) { a = min(a, b); }
const ll INF = 0x3f3f3f3f, LLINF = 0x3f3f3f3f3f3f3f3f;

struct Seg {
    int l, r, x;
    bool operator<(const Seg &o) const {
        return l == o.l ? x < o.x : l < o.l;
    }
};

ostream& operator<<(ostream& out, const Seg o) {
    out << "(l=" << o.l << ", r=" << o.r << ", x=" << o.x << ")";
    return out;
}

const int MN = 2e5 + 10;
int N, M,
    val[MN];
set<Seg> segs;

struct DSU {
    vector<int> dsu;
    vector<set<int>> ind;
    void init(int N) {
        dsu.resize(N + 1);
        ind.resize(N + 1);
        iota(dsu.begin(), dsu.end(), 0);
    }
    int rt(int x) { return dsu[x] == x ? x : dsu[x] = rt(dsu[x]); }
    void merge(int x, int y) { // x -> y
        int rx = rt(x), ry = rt(y);
        if (SZ(ind[ry]) > SZ(ind[rx])) ind[rx].swap(ind[ry]);
        ind[ry].insert(all(ind[rx]));
        dsu[rx] = ry;
    }
    set<int>& gind(int x) { return ind[rt(x)]; }
    bool same(int a, int b) { return rt(a) == rt(b); }
};

DSU dsu;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> (N) >> (M);
    for (auto i = 1; i <= N; i++)
        cin >> (val[i]);

    segs.insert({-INF, -1, -1});
    segs.insert({INF, -1, -1});
    dsu.init(N);
    int pre = 1;
    for (auto i = 1; i <= N; i++) {
        if (val[i] != val[pre]) {
            segs.insert({pre, i - 1, val[pre]});
            dsu.ind[val[pre]].insert(pre);
            pre = i;
        }
    }
    segs.insert({pre, N, val[pre]});
    dsu.ind[val[pre]].insert(pre);

    cout << (SZ(segs) - 3) << '\n';
    for (auto i = 1; i < M; i++) {
        int a, b;
        cin >> a >> b;

        // cout<<"a="<<(a)<<", "; cout<<"b="<<(b)<<", "; cout << "segs=["; for (auto x:segs)cout<<x<<", "; cout<<"], "; cout << endl; // db a,b,I:segs

        int oa = a, ob = b;
        dsu.merge(ob, oa);
        if (SZ(dsu.gind(a)) > SZ(dsu.gind(b))) swap(a, b);
        for (auto x : dsu.gind(b)) {
            auto pre = segs.lower_bound({x, -1, -1}), ptr = pre, nxt = pre; pre--; nxt++;
            Seg nv{ptr->l, ptr->r, ptr->x};
            segs.erase(ptr);
            if (dsu.same(pre->x, a)) {
                nv.l = pre->l;
                dsu.gind(a).erase(pre->l);
                segs.erase(pre);
            }
            if (dsu.same(nxt->x, a)) {
                nv.r = nxt->r;
                dsu.gind(a).erase(nxt->l);
                segs.erase(nxt);
            }
            dsu.gind(b).erase(ptr->l);
            segs.insert(nv);
            dsu.gind(b).erase(nv.l);
        }

        cout << (SZ(segs)-3) << '\n';
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
    #define cerr if(false)cerr
#else
    #define cerr if(true)cerr
#endif
#define inputarr(a,n) for(ll i=0;i<n;i++) cin>>a[i];
#define prllarr(a,n) for(ll i=0;i<n;i++) cerr<<a[i]<<" "; cerr<<endl;
#define pb push_back
#define ll long long
#define mod 1000000007
#define foi ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(0);
#define in(n) scanf("%lld",&n);
#define in2(x,y) scanf("%lld %lld",&(x),&(y));
#define in3(x,y,z) scanf("%lld %lld %lld",&(x),&(y),&(z));
#define in4(x,y,z,m) scanf("%lld %lld %lld %lld",&(x),&(y),&(z),&(m));
#define out(n) printf("%lld\n",n);
#define out2(x,y) printf("%lld %lld\n",x,y);
#define test(t)  ll t; in(t);while(t--)
#define set(arr,n,s) for(ll i=0;i<n;i++){arr[i]=s;}
#define fr(i,s,e) for(ll i=s;i<e;i++)
#define frr(i,s,e) for(ll i=e-1;i>=s;i--)
#define vi vector<ll>
#define see2(x,y) cerr<<x<<" "<<y<<endl;
#define see(x) cerr<<x<<endl;
#define see3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define see4(x,y,z,m) cout<<x<<" "<<y<<" "<<z<<" "<<m<<endl;
#define invec(a,n) fr(i,0,n){ll x;in(x) a.pb(x);}
#define vii vector<pair<ll,ll> >
#define all(a) a.begin(),a.end()
#define pii pair<ll,ll>

ll power(ll x,ll y,ll p){ll res=1;x=x%p;while(y>0){if(y&1){res=(res*x)%p;} y=y>>1;x=(x*x)%p;}return res;}
ll modInverse(ll a,ll p){return power(a,p-2,p);}//used with feemat little//only for prime
// void gcd(ll a, ll b, ll& d, ll& u, ll& v) {
//     if (b == 0) {
//         d = a;
//         u = 1;
//         v = 0;
//     } else {
//         gcd(b, a % b, d, v, u);
//         // a u + b v = b u' + (a - (a/b) * b) v'
//         // = a v' + b (u' - (a/b) v').
//         v -= a / b * u;
//     }
// }
// ll Inverse(ll a, ll m) {
//     a %= m;
//     if (a < 0) a += m;
//     ll d, u, v;
//     gcd(a, m, d, u, v);
//     assert(d == 1);
//     u %= m;
//     if (u < 0) u += m;
//     return u;
// }

// ll gcd(ll x,ll y){if(x==0 || y==0){return max(y,x);}return gcd(y%x,x);}
// ll gcdExtended(ll a,ll b,ll &x,ll &y){if(a==0){x=0;y=1;return b;}ll x1,y1;ll gcd = gcdExtended(b%a,a,x1,y1);x=y1-(b/a)*x1;y=x1;return gcd;}//o(log(b))
// ;

ll grp[200005],pa[200005],size[200006];
vi pre[200005];
ll get(ll x){
    if(x==pa[x])return x;
    return pa[x]=get(pa[x]);
}
int main(){
    ll n,m;
    in2(n,m)
    for(ll i=1;i<=n;i++){
        ll x;
        in(x)
        grp[i]=x;
        pre[x].pb(i);
    }
    for(ll i=1;i<=m;i++){
        pa[i]=i;
        size[i]=pre[i].size();
    }
    ll ans=n-1;
    for(ll i=0;i<m;i++){
        if(i==0){
            for(ll j=1;j<n;j++){
                ll z=grp[j]==grp[j+1];

                ans-=z;
            }
            cout<<ans<<endl;
            continue;
        }
        ll x,y;
        in2(x,y);
        x=get(x);
        y=get(y);
        if(size[x]>size[y]){
            swap(x,y);
        }
        for(auto p:pre[x]){
            if(p!=0)if(grp[p-1]==y)ans--;
            if(p!=n)if(grp[p+1]==y)ans--;
        }
        for(auto p:pre[x]){
            pre[y].pb(p);
            grp[p]=y;
        }
        pre[x].clear();
        cout<<ans<<endl;
        pa[x]=y;
        size[y]+=size[x];

    }

}
/*error-----
convert every int to long long eg-1LL
create array with proper analysis of problem constrain
check mod also
*/


#include <bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
    #define cerr if(false)cerr
#else
    #define cerr if(true)cerr
#endif
#define inputarr(a,n) for(ll i=0;i<n;i++) cin>>a[i];
#define prllarr(a,n) for(ll i=0;i<n;i++) cerr<<a[i]<<" "; cerr<<endl;
#define pb push_back
#define ll long long
#define mod 1000000007
#define foi ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(0);
#define in(n) scanf("%lld",&n);
#define in2(x,y) scanf("%lld %lld",&(x),&(y));
#define in3(x,y,z) scanf("%lld %lld %lld",&(x),&(y),&(z));
#define in4(x,y,z,m) scanf("%lld %lld %lld %lld",&(x),&(y),&(z),&(m));
#define out(n) printf("%lld\n",n);
#define out2(x,y) printf("%lld %lld\n",x,y);
#define test(t)  ll t; in(t);while(t--)
#define set(arr,n,s) for(ll i=0;i<n;i++){arr[i]=s;}
#define fr(i,s,e) for(ll i=s;i<e;i++)
#define frr(i,s,e) for(ll i=e-1;i>=s;i--)
#define vi vector<ll>
#define see2(x,y) cerr<<x<<" "<<y<<endl;
#define see(x) cerr<<x<<endl;
#define see3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define see4(x,y,z,m) cout<<x<<" "<<y<<" "<<z<<" "<<m<<endl;
#define invec(a,n) fr(i,0,n){ll x;in(x) a.pb(x);}
#define vii vector<pair<ll,ll> >
#define all(a) a.begin(),a.end()
#define pii pair<ll,ll>

ll power(ll x,ll y,ll p){ll res=1;x=x%p;while(y>0){if(y&1){res=(res*x)%p;} y=y>>1;x=(x*x)%p;}return res;}
ll modInverse(ll a,ll p){return power(a,p-2,p);}//used with feemat little//only for prime
// void gcd(ll a, ll b, ll& d, ll& u, ll& v) {
//     if (b == 0) {
//         d = a;
//         u = 1;
//         v = 0;
//     } else {
//         gcd(b, a % b, d, v, u);
//         // a u + b v = b u' + (a - (a/b) * b) v'
//         // = a v' + b (u' - (a/b) v').
//         v -= a / b * u;
//     }
// }
// ll Inverse(ll a, ll m) {
//     a %= m;
//     if (a < 0) a += m;
//     ll d, u, v;
//     gcd(a, m, d, u, v);
//     assert(d == 1);
//     u %= m;
//     if (u < 0) u += m;
//     return u;
// }

// ll gcd(ll x,ll y){if(x==0 || y==0){return max(y,x);}return gcd(y%x,x);}
// ll gcdExtended(ll a,ll b,ll &x,ll &y){if(a==0){x=0;y=1;return b;}ll x1,y1;ll gcd = gcdExtended(b%a,a,x1,y1);x=y1-(b/a)*x1;y=x1;return gcd;}//o(log(b))
// ;

ll grp[200005],pa[200005],size[200006];
vi pre[200005];
ll get(ll x){
    if(x==pa[x])return x;
    return pa[x]=get(pa[x]);
}
int main(){
    ll n,m;
    in2(n,m)
    for(ll i=1;i<=n;i++){
        ll x;
        in(x)
        grp[i]=x;
        pre[x].pb(i);
    }
    for(ll i=1;i<=m;i++){
        pa[i]=i;
        size[i]=pre[i].size();
    }
    ll ans=n-1;
    for(ll i=0;i<m;i++){
        if(i==0){
            for(ll j=1;j<n;j++){
                ll z=grp[j]==grp[j+1];

                ans-=z;
            }
            cout<<ans<<endl;
            continue;
        }
        ll x,y;
        in2(x,y);
        x=get(x);
        y=get(y);
        if(size[x]>size[y]){
            swap(x,y);
        }
        for(auto p:pre[x]){
            if(p!=0)if(grp[p-1]==y)ans--;
            if(p!=n)if(grp[p+1]==y)ans--;
        }
        for(auto p:pre[x]){
            pre[y].pb(p);
            grp[p]=y;
        }
        pre[x].clear();
        cout<<ans<<endl;
        pa[x]=y;
        size[y]+=size[y];

    }

}
/*error-----
convert every int to long long eg-1LL
create array with proper analysis of problem constrain
check mod also
*/


#include <bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
    #define cerr if(false)cerr
#else
    #define cerr if(true)cerr
#endif
#define inputarr(a,n) for(ll i=0;i<n;i++) cin>>a[i];
#define prllarr(a,n) for(ll i=0;i<n;i++) cerr<<a[i]<<" "; cerr<<endl;
#define pb push_back
#define ll long long
#define mod 1000000007
#define foi ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(0);
#define in(n) scanf("%lld",&n);
#define in2(x,y) scanf("%lld %lld",&(x),&(y));
#define in3(x,y,z) scanf("%lld %lld %lld",&(x),&(y),&(z));
#define in4(x,y,z,m) scanf("%lld %lld %lld %lld",&(x),&(y),&(z),&(m));
#define out(n) printf("%lld\n",n);
#define out2(x,y) printf("%lld %lld\n",x,y);
#define test(t)  ll t; in(t);while(t--)
#define set(arr,n,s) for(ll i=0;i<n;i++){arr[i]=s;}
#define fr(i,s,e) for(ll i=s;i<e;i++)
#define frr(i,s,e) for(ll i=e-1;i>=s;i--)
#define vi vector<ll>
#define see2(x,y) cerr<<x<<" "<<y<<endl;
#define see(x) cerr<<x<<endl;
#define see3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define see4(x,y,z,m) cout<<x<<" "<<y<<" "<<z<<" "<<m<<endl;
#define invec(a,n) fr(i,0,n){ll x;in(x) a.pb(x);}
#define vii vector<pair<ll,ll> >
#define all(a) a.begin(),a.end()
#define pii pair<ll,ll>

ll power(ll x,ll y,ll p){ll res=1;x=x%p;while(y>0){if(y&1){res=(res*x)%p;} y=y>>1;x=(x*x)%p;}return res;}
ll modInverse(ll a,ll p){return power(a,p-2,p);}//used with feemat little//only for prime
// void gcd(ll a, ll b, ll& d, ll& u, ll& v) {
//     if (b == 0) {
//         d = a;
//         u = 1;
//         v = 0;
//     } else {
//         gcd(b, a % b, d, v, u);
//         // a u + b v = b u' + (a - (a/b) * b) v'
//         // = a v' + b (u' - (a/b) v').
//         v -= a / b * u;
//     }
// }
// ll Inverse(ll a, ll m) {
//     a %= m;
//     if (a < 0) a += m;
//     ll d, u, v;
//     gcd(a, m, d, u, v);
//     assert(d == 1);
//     u %= m;
//     if (u < 0) u += m;
//     return u;
// }

// ll gcd(ll x,ll y){if(x==0 || y==0){return max(y,x);}return gcd(y%x,x);}
// ll gcdExtended(ll a,ll b,ll &x,ll &y){if(a==0){x=0;y=1;return b;}ll x1,y1;ll gcd = gcdExtended(b%a,a,x1,y1);x=y1-(b/a)*x1;y=x1;return gcd;}//o(log(b))
// ;

ll grp[200005],pa[200005],size[200006];
vi pre[200005];
ll get(ll x){
    if(x==pa[x])return x;
    return pa[x]=get(pa[x]);
}
int main(){
    ll n,m;
    in2(n,m)
    for(ll i=1;i<=n;i++){
        ll x;
        in(x)
        grp[i]=x;
        pre[x].pb(i);
    }
    for(ll i=1;i<=m;i++){
        pa[i]=i;
        size[i]=pre[i].size();
    }
    ll ans=n-1;
    for(ll i=0;i<m;i++){
        if(i==0){
            for(ll j=1;j<n;j++){
                ll z=grp[j]==grp[j+1];

                ans-=z;
            }
            cout<<ans<<endl;
            continue;
        }
        ll x,y;
        in2(x,y);
        x=get(x);
        y=get(y);
        if(size[x]>size[y]){
            swap(x,y);
        }
        for(auto p:pre[x]){
            if(p!=0)if(grp[p-1]==y)ans--;
            if(p!=n)if(grp[p+1]==y)ans--;
        }
        for(auto p:pre[x]){
            pre[y].pb(p);
            grp[p]=y;
        }
        cout<<ans<<endl;
        pa[x]=y;
        size[y]+=size[y];

    }

}
/*error-----
convert every int to long long eg-1LL
create array with proper analysis of problem constrain
check mod also
*/


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

int n, m;
int id[200005];
int mid[200005];
set<int> s[200005];

void solve()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        mid[i]=i;
    }
    int ans = n - 1;
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &id[i]);
        s[id[i]].insert(i);
        auto it = s[id[i]].find(i);
        if (it != s[id[i]].begin())
        {
            auto nit = it;
            --nit;
            if (*nit == i - 1)
            {
                --ans;
            }
        }
        ++it;
        if (it != s[id[i]].end())
        {
            if (*it == i + 1)
            {
                --ans;
            }
        }
    }
    printf("%d\n", ans);
    for(int mi = 1; mi < m; ++mi)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        while(mid[u]!=mid[mid[u]]){
            int t = mid[u];
            mid[u] = mid[mid[u]];
            u = t;
        }
        while(mid[v]!=mid[mid[v]]){
            int t = mid[v];
            mid[v] = mid[mid[v]];
            v = t;
        }
        u=mid[u];
        v=mid[v];
        if (s[u].size() < s[v].size())
        {
            swap(u, v);
        }
        auto it = s[v].begin();
        while (it != s[v].end())
        {
            int i = *it;
            //printf("v=%d i=%d\n",v,i);
            auto nit = s[u].lower_bound(i);
            if (nit != s[u].end() && *nit == i + 1)
            {
                --ans;
            }
            if (nit != s[u].begin())
            {
                --nit;
                if (*nit == i - 1)
                {
                    --ans;
                }
            }
            ++it;
        }
        for (auto &i : s[v])
        {
            s[u].insert(i);
        }
        mid[v]=u;
        printf("%d\n", ans);
    }
    return;
}

int main()
{
#ifdef purinliang
    freopen("D.txt", "r", stdin);
#endif // purinliang
    solve();
    return 0;
}


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

const int N = 2e5 + 5;
int n, m;

class DisjointSet {
  private:
    int n;
    int pa[N];
  public:
    void Init(int _n) {
        n = _n;
        for(int i = 1; i <= n; ++i)
            pa[i] = i;
        return;
    }
    int Find(int x) {
        int t = pa[x];
        while(x != t) {
            pa[x] = pa[t];
            x = t;
            t = pa[x];
        }
        return x;
    }
    void Union(int u, int v) {
        u = Find(u), v = Find(v);
        pa[v] = u;
        return;
    }
} dsu;

set<int> s[N];

void solve() {
    scanf("%d%d", &n, &m);
    dsu.Init(m);
    int ans = n - 1;
    for (int i = 1; i <= n; ++i) {
        int x;
        scanf("%d", &x);
        s[x].insert(i);
        auto it = s[x].find(i);
        if (it != s[x].begin()) {
            auto nit = it;
            --nit;
            if (*nit == i - 1)
                --ans;
        }
        ++it;
        if (it != s[x].end() && *it == i + 1)
            --ans;
    }
    printf("%d\n", ans);
    for(int mi = 1; mi < m; ++mi) {
        int u, v;
        scanf("%d%d", &u, &v);
        u = dsu.Find(u), v = dsu.Find(v);
        if (s[u].size() < s[v].size())
            swap(u, v);
        auto it = s[v].begin();
        while (it != s[v].end()) {
            int i = *it;
            auto nit = s[u].lower_bound(i);
            if (nit != s[u].end() && *nit == i + 1)
                --ans;
            if (nit != s[u].begin()) {
                --nit;
                if (*nit == i - 1)
                    --ans;
            }
            ++it;
        }
        for (auto &i : s[v])
            s[u].insert(i);
        dsu.Union(u, v);
        printf("%d\n", ans);
    }
    return;
}

int main() {
#ifdef purinliang
    freopen("E.txt", "r", stdin);
#endif // purinliang
    solve();
    return 0;
}


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

const int N = 2e5 + 5;
int n, m;

class DisjointSet {
  private:
    int n;
    int pa[N];
  public:
    void Init(int n) {
        this->n = n;
        for(int i = 1; i <= n; ++i)
            pa[i] = i;
        return;
    }
    int Root(int x) {
        while(x != pa[x]) {
            int t = pa[x];
            pa[x] = pa[t];
            x = t;
        }
        return pa[x];
    }
    void Merge(int u, int v) {
        u = Root(u), v = Root(v);
        pa[v] = u;
        return;
    }
} dsu;

set<int> s[N];

void solve() {
    scanf("%d%d", &n, &m);
    dsu.Init(n);
    int ans = n - 1;
    for (int i = 1; i <= n; ++i) {
        int x;
        scanf("%d", &x);
        s[x].insert(i);
        auto it = s[x].find(i);
        if (it != s[x].begin()) {
            auto nit = it;
            --nit;
            if (*nit == i - 1)
                --ans;
        }
        ++it;
        if (it != s[x].end() && *it == i + 1)
            --ans;
    }
    printf("%d\n", ans);
    for(int mi = 1; mi < m; ++mi) {
        int u, v;
        scanf("%d%d", &u, &v);
        u = dsu.Root(u), v = dsu.Root(v);
        if (s[u].size() < s[v].size())
            swap(u, v);
        auto it = s[v].begin();
        while (it != s[v].end()) {
            int i = *it;
            auto nit = s[u].lower_bound(i);
            if (nit != s[u].end() && *nit == i + 1)
                --ans;
            if (nit != s[u].begin()) {
                --nit;
                if (*nit == i - 1)
                    --ans;
            }
            ++it;
        }
        for (auto &i : s[v])
            s[u].insert(i);
        dsu.Merge(u, v);
        printf("%d\n", ans);
    }
    return;
}

int main() {
#ifdef purinliang
    freopen("E.txt", "r", stdin);
#endif // purinliang
    solve();
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=200010,M=MOD;
int n,m,a,b,ans,dif[N];
set<int> tw[N];
struct DSU{
    int p[N];
    DSU(){seto(p,-1);}
    int head(int x){return p[x]<0? x: p[x]=head(p[x]);}
    bool link(int x,int y){
        x=head(x); y=head(y);
        if(x==y) return 0;
        //if(p[x]>p[y]) swap(x,y);
        p[x]+=p[y]; p[y]=x;
        return 1;
    }
} dsu;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m;
    fori(0,n){
        cin>>a;
        if(!sz(tw[a])||*tw[a].rbegin()<i-1) dif[a]++;
        tw[a].insert(i);
    }
    fori(1,m+1) ans+=dif[i];
    cout<<ans-1<<nl;
    foru(cnt,1,m){
        cin>>a>>b; a=dsu.head(a); b=dsu.head(b);
        if(sz(tw[a])<sz(tw[b])) swap(a,b);
        ans-=dif[a]+dif[b];
        for(auto i:tw[b]){
            dif[a]++;
            if(sz(tw[a])&&*--tw[a].lower_bound(i)==i-1) dif[a]--;
            if(tw[a].lower_bound(i)!=tw[a].end()&&*tw[a].lower_bound(i)==i+1) dif[a]--;
            tw[a].insert(i);
        }
        dsu.link(a,b); ans+=dif[a];
        cout<<ans-1<<nl;
    }
    return 0;
}
/**

*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second//
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=200010,M=MOD;
int n,m,a,b,ans,dif[N];
set<int> tw[N];
struct DSU{
    int p[N];
    DSU(){seto(p,-1);}
    int head(int x){return p[x]<0? x: p[x]=head(p[x]);}
    bool link(int x,int y){
        x=head(x); y=head(y);
        if(x==y) return 0;
        //if(p[x]>p[y]) swap(x,y);
        p[x]+=p[y]; p[y]=x;
        return 1;
    }
} dsu;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m;
    fori(0,n){
        cin>>a;
        if(!sz(tw[a])||*tw[a].rbegin()<i-1) dif[a]++;
        tw[a].insert(i);
    }
    fori(1,m+1) ans+=dif[i];
    cout<<ans-1<<nl;
    foru(cnt,1,m){
        cin>>a>>b; a=dsu.head(a); b=dsu.head(b);
        if(sz(tw[a])<sz(tw[b])) swap(a,b);
        ans-=dif[a]+dif[b];
        for(auto i:tw[b]){
            dif[a]++;
            if(tw[a].lower_bound(i)!=tw[a].begin()&&*--tw[a].lower_bound(i)==i-1) dif[a]--;
            if(tw[a].lower_bound(i)!=tw[a].end()&&*tw[a].lower_bound(i)==i+1) dif[a]--;
            tw[a].insert(i);
        }
        dsu.link(a,b); ans+=dif[a];
        cout<<ans-1<<nl;
    }
    return 0;
}
/**

*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=200010,M=MOD;
int n,m,a,b,ans,dif[N];
set<int> tw[N];
struct DSU{
    int p[N];
    DSU(){seto(p,-1);}
    int head(int x){return p[x]<0? x: p[x]=head(p[x]);}
    bool link(int x,int y){
        x=head(x); y=head(y);
        if(x==y) return 0;
        //if(p[x]>p[y]) swap(x,y);
        p[x]+=p[y]; p[y]=x;
        return 1;
    }
} dsu;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m;
    fori(0,n){
        cin>>a;
        if(!sz(tw[a])||*tw[a].rbegin()<i-1) dif[a]++;
        tw[a].insert(i);
    }
    fori(1,m+1) ans+=dif[i];
    cout<<ans-1<<nl;
    foru(cnt,1,m){
        cin>>a>>b; a=dsu.head(a); b=dsu.head(b);
        if(sz(tw[a])<sz(tw[b])) swap(a,b);
        ans-=dif[a]+dif[b];
        for(auto i:tw[b]){
            dif[a]++;
            if(sz(tw[a])&&*--tw[a].lower_bound(i)==i-1) dif[a]--;
            if(sz(tw[a])&&*tw[a].lower_bound(i)==i+1) dif[a]--;
            tw[a].insert(i);
        }
        dsu.link(a,b); ans+=dif[a];
        cout<<ans-1<<nl;
    }
    return 0;
}
/**

*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=200010,M=MOD;
int n,m,a,b,ans,dif[N];
set<int> tw[N];
struct DSU{
    int p[N];
    DSU(){seto(p,-1);}
    int head(int x){return p[x]<0? x: p[x]=head(p[x]);}
    bool link(int x,int y){
        x=head(x); y=head(y);
        if(x==y) return 0;
        //if(p[x]>p[y]) swap(x,y);
        p[x]+=p[y]; p[y]=x;
        return 1;
    }
} dsu;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m;
    fori(0,n){
        cin>>a;
        if(!sz(tw[a])||*tw[a].rbegin()<i-1) dif[a]++;
        tw[a].insert(i);
    }
    fori(1,m+1) ans+=dif[i];
    cout<<ans-1<<nl;
    foru(cnt,1,m){
        cin>>a>>b; a=dsu.head(a); b=dsu.head(b);
        if(sz(tw[a])<sz(tw[b])) swap(a,b);
        ans-=dif[a]+dif[b];
        for(auto i:tw[b]){
            dif[a]++;
            if(tw[a].lower_bound(i)!=tw[a].begin()&&*--tw[a].lower_bound(i)==i-1) dif[a]--;
            if(tw[a].lower_bound(i)!=tw[a].end()&&*tw[a].lower_bound(i)==i+1) dif[a]--;
            tw[a].insert(i);
        }
        dsu.link(a,b); ans+=dif[a];
        cout<<ans-1<<nl;
    }
    return 0;
}
/**

*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=200010,M=MOD;
int n,m,a,b,ans,dif[N];
set<int> tw[N];
struct DSU{
    int p[N];
    DSU(){seto(p,-1);}
    int head(int x){return p[x]<0? x: p[x]=head(p[x]);}
    bool link(int x,int y){
        x=head(x); y=head(y);
        if(x==y) return 0;
        if(p[x]>p[y]) swap(x,y);
        p[x]+=p[y]; p[y]=x;
        return 1;
    }
} dsu;

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m;
    fori(0,n){
        cin>>a;
        if(!sz(tw[a])||*tw[a].rbegin()<i-1) dif[a]++;
        tw[a].insert(i);
    }
    fori(1,m+1) ans+=dif[i];
    cout<<ans-1<<nl;
    foru(cnt,1,m){
        cin>>a>>b; a=dsu.head(a); b=dsu.head(b);
        if(sz(tw[a])<sz(tw[b])) swap(a,b);
        ans-=dif[a]+dif[b];
        for(auto i:tw[b]){
            dif[a]++;
            if(sz(tw[a])&&*--tw[a].lower_bound(i)==i-1) dif[a]--;
            if(sz(tw[a])&&*tw[a].lower_bound(i)==i+1) dif[a]--;
            tw[a].insert(i);
        }
        dsu.link(a,b); ans+=dif[a];
        cout<<ans-1<<nl;
    }
    return 0;
}
/**

*/


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m,p[N],sumEdg,t[N],rnk[N];
vector<int> edg[N];
vector<int> tow[N];

int findSet(int u) {return u==p[u]?u:p[u]=findSet(p[u]);}
void joinSet(int s, int d) {
	cerr<<"Join "<<s<<" "<<d<<"\n";
	int y=findSet(d);
	for (int v : edg[s]) {
		if (findSet(v)==s) continue;
		if (findSet(v) != y) {
			edg[d].push_back(v);
		}
		else --sumEdg;
	}
	edg[s].clear();
	rnk[d]=edg[d].size();
	rnk[s]=0;
}
void unionSet(int u, int v) {
	cerr<<"Union "<<u<<" "<<v<<"\n";
	int x=findSet(u), y=findSet(v);
	if (x!=y) {
		cerr<<"Rank["<<u<<","<<v<<"] = "<<rnk[x]<<","<<rnk[y]<<"\n";
		if (rnk[x]>=rnk[y]) {
			joinSet(y,x);
			p[y]=x;
		}
		else {
			p[x]=y;
			joinSet(x,y);
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for (int i=1; i<=n; ++i) p[i]=i;
	for (int i=1; i<=n; ++i) {
		cin>>t[i];
		tow[t[i]].push_back(i);
	}
	for (int i=1; i<n; ++i) {
		edg[i].push_back(i+1);
		edg[i+1].push_back(i);
		rnk[i]=2;
	}
	sumEdg=n-1;
	for (int i=1; i<=m; ++i) {
		if (!tow[i].empty()) {
			for (int x : tow[i])
				unionSet(x, tow[i][0]);
		}
	}
	cout<<sumEdg<<"\n";
	for (int i=1; i<m; ++i) {
		int a,b; cin>>a>>b;
		unionSet(tow[a][0], tow[b][0]);
		cout<<sumEdg<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m,p[N],sumEdg,t[N],rnk[N];
vector<int> edg[N];
vector<int> tow[N];

int findSet(int u) {return u==p[u]?u:p[u]=findSet(p[u]);}
void joinSet(int s, int d) {
	//cerr<<"Join "<<s<<" "<<d<<"\n";
	for (int v : edg[s]) {
		if (findSet(v)==s) continue;
		if (findSet(v) != d) {
			edg[d].push_back(v);
		}
		else --sumEdg;
	}
	edg[s].clear();
	rnk[d]=edg[d].size();
	rnk[s]=0;
}
void unionSet(int u, int v) {
	//cerr<<"Union "<<u<<" "<<v<<"\n";
	int x=findSet(u), y=findSet(v);
	if (x!=y) {
		//cerr<<"Rank["<<u<<","<<v<<"] = "<<rnk[x]<<","<<rnk[y]<<"\n";
		if (rnk[x]>=rnk[y]) {
			joinSet(y,x);
			p[y]=x;
		}
		else {
			joinSet(x,y);
			p[x]=y;
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for (int i=1; i<=n; ++i) p[i]=i;
	for (int i=1; i<=n; ++i) {
		cin>>t[i];
		tow[t[i]].push_back(i);
	}
	for (int i=1; i<n; ++i) {
		edg[i].push_back(i+1);
		edg[i+1].push_back(i);
		rnk[i]=2;
	}
	sumEdg=n-1; rnk[n]=1;
	for (int i=1; i<=m; ++i) {
		if (!tow[i].empty()) {
			for (int x : tow[i])
				unionSet(x, tow[i][0]);
		}
	}
	cout<<sumEdg<<"\n";
	for (int i=1; i<m; ++i) {
		int a,b; cin>>a>>b;
		unionSet(tow[a][0], tow[b][0]);
		cout<<sumEdg<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m,p[N],sumEdg,t[N],rnk[N];
vector<int> edg[N];
vector<int> tow[N];

int findSet(int u) {return u==p[u]?u:p[u]=findSet(p[u]);}
void joinSet(int s, int d) {
	cerr<<"Join "<<s<<" "<<d<<"\n";
	int x=findSet(s), y=findSet(d);
	for (int v : edg[s]) {
		if (findSet(v)==x) continue;
		if (findSet(v) != y) {
			edg[d].push_back(v);
		}
		else --sumEdg;
	}
	edg[s].clear();
	rnk[d]=edg[d].size();
	rnk[s]=0;
}
void unionSet(int u, int v) {
	cerr<<"Union "<<u<<" "<<v<<"\n";
	int x=findSet(u), y=findSet(v);
	if (x!=y) {
		cerr<<"Rank["<<u<<","<<v<<"] = "<<rnk[x]<<","<<rnk[y]<<"\n";
		if (rnk[x]>=rnk[y]) {
			joinSet(y,x);
			p[y]=x;
		}
		else {
			joinSet(x,y);
			p[x]=y;
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for (int i=1; i<=n; ++i) p[i]=i;
	for (int i=1; i<=n; ++i) {
		cin>>t[i];
		tow[t[i]].push_back(i);
	}
	for (int i=1; i<n; ++i) {
		edg[i].push_back(i+1);
		edg[i+1].push_back(i);
		rnk[i]=2;
	}
	sumEdg=n-1; rnk[n]=1;
	for (int i=1; i<=m; ++i) {
		if (!tow[i].empty()) {
			for (int x : tow[i])
				unionSet(x, tow[i][0]);
		}
	}
	cout<<sumEdg<<"\n";
	for (int i=1; i<m; ++i) {
		int a,b; cin>>a>>b;
		unionSet(tow[a][0], tow[b][0]);
		cout<<sumEdg<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vpll vector < pair<long long,long long> >
#define fill(a,val)  memset(a,val, sizeof (a))
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define all(cont) cont.begin(), cont.end()
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define MAX   1e9
#define MIN  -1e9
typedef map<int,int> mpi;
typedef set<int> seti;
typedef multiset<int> mseti;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define rep(i, n)    for(long long int i = 0; i < (n); ++i)
#define repA(i, a, n)  for(int i = a; i <= (n); ++i)
#define repD(i, a, n)  for(int i = a; i >= (n); --i)
#define repn(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define trav(a, x) for(auto& a : x)
struct Interval{ll start,end;};
bool compare(Interval i1, Interval i2) {return (i1.start < i2.start);}

vll p,belongs;
vvi towers;

ll getparent(ll s){
	return p[s] == s ? s: p[s] = getparent(p[s]);
}

int main(){
	fio;
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	#endif
	ll n,m;
	cin>>n>>m;
	p.resize(m);
	belongs.resize(n);
	towers.resize(m);
	rep(i,m){
		p[i] = i;
	}
	ll ans = n - 1;
	rep(i,n){
		ll tower;
		cin>>tower;
		belongs[i] = tower - 1;
		towers[tower - 1].pb(i);
		ans-= i && (belongs[i] == belongs[i-1]);
	}
	cout<<ans<<"\n";
	rep(i,m-1){
		ll u,v;
		cin>>u>>v;
		u--;v--;
		u = getparent(u);
		v = getparent(v);
		// if(towers[v].size() < towers[u].size()){
		// 	swap(u,v);
		// }
		for(auto disc:towers[u]){
			ans-= disc && belongs[disc - 1] == v;
			ans-= (disc < n - 1) && belongs[disc + 1] == v;
		}
		for(auto disc:towers[u]){
			towers[v].pb(disc);
			belongs[disc] = v;
		}
		p[u] = v;
		towers[u].clear();
		cout<<ans<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vpll vector < pair<long long,long long> >
#define fill(a,val)  memset(a,val, sizeof (a))
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define all(cont) cont.begin(), cont.end()
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define MAX   1e9
#define MIN  -1e9
typedef map<int,int> mpi;
typedef set<int> seti;
typedef multiset<int> mseti;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define rep(i, n)    for(long long int i = 0; i < (n); ++i)
#define repA(i, a, n)  for(int i = a; i <= (n); ++i)
#define repD(i, a, n)  for(int i = a; i >= (n); --i)
#define repn(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define trav(a, x) for(auto& a : x)
struct Interval{ll start,end;};
bool compare(Interval i1, Interval i2) {return (i1.start < i2.start);}

vll p,belongs;
vvi towers;

ll getparent(ll s){
	return p[s] == s ? s: p[s] = getparent(p[s]);
}

int main(){
	fio;
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	#endif
	ll n,m;
	cin>>n>>m;
	p.resize(m);
	belongs.resize(n);
	towers.resize(m);
	rep(i,m){
		p[i] = i;
	}
	ll ans = n - 1;
	rep(i,n){
		ll tower;
		cin>>tower;
		belongs[i] = tower - 1;
		towers[tower - 1].pb(i);
		ans-= i && (belongs[i] == belongs[i-1]);
	}
	cout<<ans<<"\n";
	rep(i,m-1){
		ll u,v;
		cin>>u>>v;
		u--;v--;
		u = getparent(u);
		v = getparent(v);
		// if(towers[v].size() < towers[u].size()){
		// 	swap(u,v);
		// }
		for(auto disc:towers[u]){
			ans-= disc && belongs[disc - 1] == v;
			ans-= (disc < n - 1) && belongs[disc + 1] == v;
		}
		// for(auto disc:towers[u]){
		// 	towers[v].pb(disc);
		// 	belongs[disc] = v;
		// }
		while(!towers[u].empty()){
			towers[v].pb(*(towers[u].begin()));
			belongs[*(towers[u].begin())] = v;
			towers[u].erase(towers[u].begin());
		}
		p[u] = v;
		cout<<ans<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vpll vector < pair<long long,long long> >
#define fill(a,val)  memset(a,val, sizeof (a))
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define all(cont) cont.begin(), cont.end()
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define MAX   1e9
#define MIN  -1e9
typedef map<int,int> mpi;
typedef set<int> seti;
typedef multiset<int> mseti;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define rep(i, n)    for(long long int i = 0; i < (n); ++i)
#define repA(i, a, n)  for(int i = a; i <= (n); ++i)
#define repD(i, a, n)  for(int i = a; i >= (n); --i)
#define repn(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define trav(a, x) for(auto& a : x)
struct Interval{ll start,end;};
bool compare(Interval i1, Interval i2) {return (i1.start < i2.start);}

vll p,belongs;
vvi towers;

ll getparent(ll s){
	return p[s] == s ? s: p[s] = getparent(p[s]);
}

int main(){
	fio;
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	#endif
	ll n,m;
	cin>>n>>m;
	p.resize(m);
	belongs.resize(n);
	towers.resize(m);
	rep(i,m){
		p[i] = i;
	}
	ll ans = n - 1;
	rep(i,n){
		ll tower;
		cin>>tower;
		belongs[i] = tower - 1;
		towers[tower - 1].pb(i);
		ans-= i && (belongs[i] == belongs[i-1]);
	}
	cout<<ans<<"\n";
	rep(i,m-1){
		ll u,v;
		cin>>u>>v;
		u--;v--;
		u = getparent(u);
		v = getparent(v);
		// if(towers[v].size() < towers[u].size()){
		// 	swap(u,v);
		// }
		for(auto disc:towers[u]){
			ans-= disc && belongs[disc - 1] == v;
			ans-= (disc < n - 1) && belongs[disc + 1] == v;
		}
		for(auto disc:towers[u]){
			towers[v].pb(disc);
			belongs[disc] = v;
		}
		p[u] = v;
		cout<<ans<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vpll vector < pair<long long,long long> >
#define fill(a,val)  memset(a,val, sizeof (a))
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define all(cont) cont.begin(), cont.end()
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define MAX   1e9
#define MIN  -1e9
typedef map<int,int> mpi;
typedef set<int> seti;
typedef multiset<int> mseti;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define rep(i, n)    for(long long int i = 0; i < (n); ++i)
#define repA(i, a, n)  for(int i = a; i <= (n); ++i)
#define repD(i, a, n)  for(int i = a; i >= (n); --i)
#define repn(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define trav(a, x) for(auto& a : x)
struct Interval{ll start,end;};
bool compare(Interval i1, Interval i2) {return (i1.start < i2.start);}

vll p,belongs;
vvi towers;

ll getparent(ll s){
	return p[s] == s ? s: p[s] = getparent(p[s]);
}

int main(){
	fio;
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	#endif
	ll n,m;
	cin>>n>>m;
	p.resize(m);
	belongs.resize(n);
	towers.resize(m);
	rep(i,m){
		p[i] = i;
	}
	ll ans = n - 1;
	rep(i,n){
		ll tower;
		cin>>tower;
		belongs[i] = tower - 1;
		towers[tower - 1].pb(i);
		ans-= i && (belongs[i] == belongs[i-1]);
	}
	cout<<ans<<"\n";
	rep(i,m-1){
		ll u,v;
		cin>>u>>v;
		u--;v--;
		u = getparent(u);
		v = getparent(v);
		// if(towers[v].size() < towers[u].size()){
		// 	swap(u,v);
		// }
		for(auto disc:towers[u]){
			ans-= disc && belongs[disc - 1] == v;
			ans-= (disc < n - 1) && belongs[disc + 1] == v;
		}
		// for(auto disc:towers[u]){
		// 	towers[v].pb(disc);
		// 	belongs[disc] = v;
		// }
		seti s;
		for(auto disc:towers[u]){
			s.insert(disc);
		}
		towers[u].clear();
		while(!s.empty()){
			towers[v].pb(*(s.begin()));
			belongs[*(s.begin())] = v;
			s.erase(s.begin());
		}
		p[u] = v;
		cout<<ans<<"\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vpll vector < pair<long long,long long> >
#define fill(a,val)  memset(a,val, sizeof (a))
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define all(cont) cont.begin(), cont.end()
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define MAX   1e9
#define MIN  -1e9
typedef map<int,int> mpi;
typedef set<int> seti;
typedef multiset<int> mseti;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define rep(i, n)    for(long long int i = 0; i < (n); ++i)
#define repA(i, a, n)  for(int i = a; i <= (n); ++i)
#define repD(i, a, n)  for(int i = a; i >= (n); --i)
#define repn(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define trav(a, x) for(auto& a : x)
struct Interval{ll start,end;};
bool compare(Interval i1, Interval i2) {return (i1.start < i2.start);}

vll p,belongs;
vvi towers;

ll getparent(ll s){
	return p[s] == s ? s: p[s] = getparent(p[s]);
}

int main(){
	fio;
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	#endif
	ll n,m;
	cin>>n>>m;
	p.resize(m);
	belongs.resize(n);
	towers.resize(m);
	rep(i,m){
		p[i] = i;
	}
	ll ans = n - 1;
	rep(i,n){
		ll tower;
		cin>>tower;
		belongs[i] = tower - 1;
		towers[tower - 1].pb(i);
		ans-= i && (belongs[i] == belongs[i-1]);
	}
	cout<<ans<<"\n";
	rep(i,m-1){
		ll u,v;
		cin>>u>>v;
		u--;v--;
		u = getparent(u);
		v = getparent(v);
		if(towers[v].size() < towers[u].size()){
			swap(u,v);
		}
		for(auto disc:towers[u]){
			ans-= disc && belongs[disc - 1] == v;
			ans-= (disc < n - 1) && belongs[disc + 1] == v;
		}
		for(auto disc:towers[u]){
			towers[v].pb(disc);
			belongs[disc] = v;
		}
		p[u] = v;
		cout<<ans<<"\n";
	}
	return 0;
}


/*
 *1380E.Merging Towers
 *给出半径为1~n的n个盘子和m个塔，要求每个塔上盘子的半径始终从底向上递减
 *一次操作可以将一个塔上的任意个盘子移动到另一个塔的顶部。
 *令某一情形下的复杂度为将所有盘子移动到同一个塔上所需的最小操作数。
 *题目给出m-1次询问，每次询问时输出当前情形的复杂度并合并到两个塔的盘子到同一个塔上
  */
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int t,n,m;
vector<int> g[maxn];
int a[maxn];
int father[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}
void Union (int x,int y) {
	for (auto i:g[y]) g[x].push_back(i);
	g[y].clear();
	father[findfather(y)]=findfather(x);
}
int main () {
	int ans=0;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
		g[a[i]].push_back(i);
		if (i>1&&a[i]!=a[i-1]) ans++;
	}
	for (int i=1;i<=m;i++) father[i]=i;
	printf("%d\n",ans);
	for (int i=1;i<m;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		int faU=findfather(u);
		int faV=findfather(v);
		vector<int> tt;
		if (g[faU].size()<g[faV].size()) swap(faU,faV);
		tt=g[faV];
		for (auto j:tt) {
			int u=j-1;
			if (u>=1&&u<=n)
				if (findfather(a[u])==faU) ans--;
			u=j+1;
			if (u>=1&&u<=n)
				if (findfather(a[u])==faU) ans--;
		}
		Union(u,v);
		printf("%d\n",ans);
	}
}


/*
 *1380E.Merging Towers
 *给出半径为1~n的n个盘子和m个塔，要求每个塔上盘子的半径始终从底向上递减
 *一次操作可以将一个塔上的任意个盘子移动到另一个塔的顶部。
 *令某一情形下的复杂度为将所有盘子移动到同一个塔上所需的最小操作数。
 *题目给出m-1次询问，每次询问时输出当前情形的复杂度并合并到两个塔的盘子到同一个塔上
 *考虑如果一个一个搬碟子，答案是n-1。
 *如果有两个相邻的碟子，就把他们看成一个整体，答案可以减去1.
 *按照每堆的堆顶建树，每次合并的时候，对于小树的节点我们都判断它在原数组的相邻节点的祖先节点是不是合并的大树top点
 *如果是，既然相邻那么他们的半径就是差值最小的，也就是说可以把他们看成一个整体
  */
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
vector<int> g[maxn];
int father[maxn];
int a[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}
int main () {
	int n,m;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
		g[a[i]].push_back(i);
	}
	int wjm=n;
	for (int i=1;i<=m;i++) father[i]=i;
	for (int i=2;i<=n;i++) if (a[i-1]==a[i]) wjm--;
	printf("%d\n",wjm-1);
	for (int i=1;i<m;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		int faX=findfather(x);
		int faY=findfather(y);
		if (g[faX].size()>g[faY].size()) swap(faX,faY);
		for (int j:g[faX]) {
			if (j+1<=n&&a[j+1]==faY) wjm--;
			if (j-1>=1&&a[j-1]==faY) wjm--;
			g[faY].push_back(j);
  		}
  		for (int j:g[faX]) a[j]=faY;
  		father[faX]=faY;
  		printf("%d\n",wjm-1);
	}
}


/*
 *1380E.Merging Towers
 *给出半径为1~n的n个盘子和m个塔，要求每个塔上盘子的半径始终从底向上递减
 *一次操作可以将一个塔上的任意个盘子移动到另一个塔的顶部。
 *令某一情形下的复杂度为将所有盘子移动到同一个塔上所需的最小操作数。
 *题目给出m-1次询问，每次询问时输出当前情形的复杂度并合并到两个塔的盘子到同一个塔上
  */
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int t,n,m;
vector<int> g[maxn];
int a[maxn];
int father[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}
void Union (int x,int y) {
	for (auto i:g[y]) g[x].push_back(i);
	g[y].clear();
	father[findfather(y)]=findfather(x);
}
int main () {
	int ans=0;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
		g[a[i]].push_back(i);
		if (i>1&&a[i]!=a[i-1]) ans++;
	}
	for (int i=1;i<=m;i++) father[i]=i;
	printf("%d\n",ans);
	for (int i=1;i<m;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		int faU=findfather(u);
		int faV=findfather(v);
		vector<int> tt;
		if (g[faU].size()<g[faV].size()) swap(faU,faV);
		tt=g[faV];
		for (auto j:tt) {
			int u=j-1;
			if (u>=1&&u<=n)
				if (findfather(a[u])==faU) ans--;
			u=j+1;
			if (u>=1&&u<=n)
				if (findfather(a[u])==faU) ans--;
		}
		Union(u,v);
		printf("%d\n",ans);
	}
}