Description
N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.
例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.
Input
第一行给出N,M表示布丁的个数和好友的操作次数.
第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,
对于每个操作,
若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y.
若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0。
n,m<=1000000
Output
针对第二类操作即询问,依次输出当前有多少段颜色.
Sample Input
4 3
1 2 2 1
2
1 2 1
2
Sample Output
3
1
用到了启发式合并,就是小的数据结构合并到了大的数据结构里
#include <stdio.h>
#include <set>
const int MAXN = 1000005;
using namespace std;
set<int> st[MAXN];
int col[MAXN],fa[MAXN];
int ans;
void solve(int a,int b)
{
for(set<int>::iterator i = st[a].begin(); i != st[a].end(); i++) {
if(col[*i - 1] == b) ans--;
if(col[*i + 1] == b) ans--;
st[b].insert(*i);
}
for(set<int>::iterator i = st[a].begin(); i != st[a].end(); i++) col[*i] = b;
st[a].clear();
}
int main(void)
{
int n,m;
ans = 0;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
scanf("%d",&col[i]);
fa[col[i]] = col[i];
st[col[i]].insert(i);
if(col[i] != col[i - 1]) ans++;
}
int op;
int a,b;
while(m--) {
scanf("%d",&op);
if(op == 2) printf("%d\n",ans);
else {
scanf("%d%d",&a,&b);
if(a != b) {
if(st[fa[a]].size() > st[fa[b]].size()) {
swap(fa[a],fa[b]);
}
a = fa[a],b = fa[b];
solve(a,b);
}
}
}
return 0;
}