思路:
把相同颜色的用链表串起来,然后求一下最初值的贡献,然后进行启发式合并,将长度小的颜色的链合并到大的链表上,时间复杂度 n l o g n nlogn nlogn
参考代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int mod = 1000000007;
void read(int& v) {
int k = 1;
v = 0;
int c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
k = 0;
c = getchar();
}
while (c >= '0' && c <= '9')
v = (v << 3) + (v << 1) + (c - 48), c = getchar();
if (k == 0)
v = -v;
}
int st[maxn], f[maxn], nxt[maxn], hd[maxn], sz[maxn], c[maxn];
int ans;
void merge(int x, int y) {
for (int i = hd[x]; i; i = nxt[i])
ans -= (c[i - 1] == y) + (c[i + 1] == y);
for (int i = hd[x]; i; i = nxt[i])
c[i] = y;
nxt[st[x]] = hd[y], hd[y] = hd[x], sz[y] += sz[x];
hd[x] = sz[x] = st[x] = 0;
}
int main() {
int n, m;
read(n), read(m);
for (int i = 1; i <= n; i++) {
read(c[i]), f[c[i]] = c[i];
ans += (c[i] != c[i - 1]);
if (!hd[c[i]])
st[c[i]] = i;
sz[c[i]]++, nxt[i] = hd[c[i]], hd[c[i]] = i;
}
for (int i = 0; i < m; i++) {
int opt, x, y;
read(opt);
if (opt == 1) {
read(x), read(y);
if ((x == y))
continue;
if (sz[f[x]] > sz[f[y]])
swap(f[x], f[y]);
if (!sz[f[x]])
continue;
merge(f[x], f[y]);
} else {
printf("%d\n", ans);
}
}
}