给出一个序列,序列每个不同的数字代表不同的颜色
现在有两种操作:
1:将颜色 x 替换为颜色 y
2:询问序列中有多少段颜色
#include <bits/stdc++.h>using namespace std;const int N = 1e5+5, M = 1e6+5;int n, m, idx, ans;int h[M], e[N], ne[N];int col[N], sz[M], p[M];void add(int a, int b) {e[idx] = b, ne[idx] = h[a];h[a] = idx++, sz[a]++;}void merge(int& x, int& y) {if (x == y)return ;if (sz[x] > sz[y])swap(x, y);//遍历x颜色所在的这条链上的点for (int i = h[x]; ~i; i = ne[i]) {int j = e[i];//看每个点的两端是否为要改变的颜色ans -= (col[j-1]==y)+(col[j+1]==y);}//头插法将x颜色所在的链插到y颜色所在的链for (int i = h[x]; ~i; i = ne[i]) {int j = e[i];col[j] = y;if (ne[i] == -1) {ne[i] = h[y];h[y] = h[x];break;}}h[x] = -1;sz[y] += sz[x], sz[x] = 0;}signed main() {scanf("%d%d", &n, &m);memset(h, -1, sizeof h);for (int i = 1; i <= n; i++) {scanf("%d", &col[i]);//求出当前段数if (col[i] != col[i-1])ans++;//将每种颜色的所有序号加入对应的链add(col[i], i);}for (int i = 0; i < M; i++)p[i] = i;while (m--) {int op;scanf("%d", &op);if (op == 2) {cout << ans << '\n';} else {int x, y;scanf("%d%d", &x, &y);merge(p[x], p[y]);}}return 0;}

#include <bits/stdc++.h>using namespace std;const int N = 1e5+5, M = N*2;int n, idx, mx;int h[N], e[M], ne[M];//son[u]代表节点u的重儿子编号int col[N], cnt[N], sz[N], son[N];long long sum, ans[N];void add(int a, int b) {e[idx] = b;ne[idx] = h[a];h[a] = idx++;}int dfs_son(int u, int fa) {sz[u] = 1;for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];if (j == fa)continue;sz[u] += dfs_son(j, u);if (sz[j] > sz[son[u]])son[u] = j;}return sz[u];}void update(int u, int fa, int sign, int pson) {int c = col[u];cnt[c] += sign;if (cnt[c] > mx) {mx = cnt[c];sum = c;} else if (cnt[c] == mx) {sum += c;}for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];if (j==fa || j==pson)continue;update(j, u, sign, pson);}}void dfs(int u, int fa, int op) {//op==0代表该点为轻儿子for (int i = h[u]; ~i; i = ne[i]) {int j =e[i];if (j==fa || j==son[u])continue;//搜当前点的轻儿子dfs(j, u, 0);}if (son[u])dfs(son[u], u, 1);update(u, fa, 1, son[u]);ans[u] = sum;//若为轻儿子,则清空整个子树if (!op) {update(u, fa, -1, 0);sum = mx = 0;}}signed main() {scanf("%d", &n);for (int i = 1; i <= n; i++)scanf("%d", &col[i]);memset(h, -1, sizeof h);for (int i = 0; i < n-1; i++) {int u, v;scanf("%d%d", &u, &v);add(u, v), add(v, u);}//求重儿子dfs_son(1, -1);//搜答案dfs(1, -1, 1);for (int i = 1; i <= n; i++)cout << ans[i] << " \n"[i==n];return 0;}
