题意:
给你序列上的初始颜色,每次把一个颜色全部改成另外一个颜色
$n \leq 10^5, color \leq 10^6, m \leq 10^6$
sol:
这题卡了一个星期,其实还是还是中间出的锅太多。
链表启发式合并即可。
注意的点:
1 : 注意在交换之后再判断$head$,因为可能交换了。
2 : 注意清空$siz$,这关系到启发式合并的正确性
3 : 注意交换的是$F[x]和F[y]$而不是$rx,ry$的$F$
#include<cstdio> #include<iostream> #define debug printf("GG\n") const int N = 1e6+7; int head[N], nxt[N], siz[N], col[N], pre[N], last[N]; int n, m, F[N], ans; void Modify(int x, int y) { // x -> y for (int o = head[x]; o; o = nxt[o]) { // col[o] = y; ans -= (col[o - 1] == y) + (col[o + 1] == y); } for (int o = head[x]; o; o = nxt[o]) col[o] = y; nxt[last[y]] = head[x], pre[head[x]] = last[y], head[x] = 0; last[y] = last[x], last[x] = 0, siz[y] += siz[x], siz[x] = 0; // 别忘了清空x 这里挂了 // Debug; } int main() { //freopen("2.in", "r", stdin); //freopen("22.out", "w", stdout); scanf("%d%d", &n, &m); for (int i = 1; i <= 1e6;F[i] = i, i++); for (int i = 1; i <= n; i++) { scanf("%d", &col[i]); if (!head[col[i]]) head[col[i]] = last[col[i]] = i; else nxt[last[col[i]]] = i, pre[i] = last[col[i]], last[col[i]] = i; if (col[i] != col[i - 1]) ans++; siz[col[i]]++; } for (int i = 1; i <= m; i++) { int opt, x, y; scanf("%d", &opt); if (opt == 2) { printf("%d\n", ans); continue; } else if (opt == 1) { scanf("%d%d", &x, &y); int rx = F[x], ry = F[y]; //if (!siz[F[x]] || rx == ry) { //debug; // continue; // } if (siz[rx] > siz[ry]) std ::swap(F[x], F[y]), std :: swap(rx, ry);//注意交换的是F[x]和F[y]而不是 if (!head[rx] || rx == ry) continue; // 判断head为空要在后面判,因为改的x可能交换了 Modify(rx, ry); } else if (opt == 3) { for (int i = 1; i <= n; i++) printf("F[%d] -> %d\n", i, F[i]); } else if (opt == 4) { for (int i = 1; i <= n; i++) printf("%d ", col[i]); } else if (opt == 5) { scanf("%d", &x); printf("%d\n", head[x]); } } return 0; }