Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 3433 Solved: 1357
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
HINT
Source
dalao讲解
由于没有时间了,代码基本是抄了一遍
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000006;
int n, m, ans, head[MAXN], nxt[MAXN], a[MAXN], col[MAXN], size[MAXN], fir[MAXN];
void modify( int x, int y ) {
for( register int i = head[x]; i; i =nxt[i] ) {
if( a[ i - 1 ] == y ) ans--;
if( a[ i + 1 ] == y ) ans--;
}
for( register int i = head[x]; i; i = nxt[i] ) a[i] = y;
nxt[fir[x]] = head[y];
head[y] = head[x];
size[y] += size[x];
head[x] = size[x] = fir[x] = 0;
}
int main( ) {
scanf( "%d%d", &n, &m );
for( register int i = 1; i <= n; i++ ) {
scanf( "%d", &a[i] );
if( a[i] != a[ i - 1 ] ) ans++;
col[a[i]] = a[i];
if( !head[a[i]] ) fir[a[i]] = i;
size[a[i]]++;
nxt[i] = head[a[i]];
head[a[i]] = i;
}
while( m-- ) { int opt, x, y;
scanf( "%d", &opt );
if( opt == 1 ) {
scanf( "%d%d", &x, &y );
if( x == y ) continue;
if( size[col[x]] > size[col[y]] ) swap( col[x], col[y] );
x = col[x], y = col[y];
if( size[x] == 0 ) continue;
modify( x, y );
} else printf( "%d\n", ans );
}
}