列表

详情


NC20076. [HNOI2009]梦幻布丁

描述

N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.

输入描述

第一行给出N,M表示布丁的个数和好友的操作次数. 
第二行N个数A1,A2...An表示第i个布丁的颜色从
第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 
若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0

输出描述

针对第二类操作即询问,依次输出当前有多少段颜色.

示例1

输入:

4 3
1 2 2 1
2
1 2 1
2

输出:

3
1

说明:

初始时布丁颜色依次为1,2,2,1,三段颜色分别为 [1, 1], [2, 3], [4, 4]。
一次操作后,布丁的颜色变为1,1,1,1,只有[1,4] 一段颜色。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 91ms, 内存消耗: 27792K, 提交时间: 2023-03-30 13:18:43

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e6 + 10;

int n, m;
int a[N];
vector<int> pos[N];
int ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		pos[a[i]].push_back(i);
	}
	
	for (int i = 1; i <= n + 1; i++) {
		ans += a[i] != a[i - 1];
	}
	
	while (m--) {
		int op, x, y;
		cin >> op;
		
		if (op == 1) {
			cin >> x >> y;
			if (x == y) continue;
			
			if (pos[x].size() > pos[y].size()) {
				pos[x].swap(pos[y]);
			}
			
			if (pos[y].size() == 0) continue;
			int col = a[pos[y][0]];
			
			for (int j = 0; j < pos[x].size(); j++) {
				int i = pos[x][j];
				pos[y].push_back(i);
				ans -= (a[i] != a[i - 1]) + (a[i] != a[i + 1]);
				a[i] = col;
				ans += (a[i] != a[i - 1]) + (a[i] != a[i + 1]);
			}
			
			pos[x].clear();
		} else {
			cout << ans - 1 << "\n";
		}
	}
	
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 138ms, 内存消耗: 31200K, 提交时间: 2019-07-10 16:21:31

#include<bits/stdc++.h>
using namespace std;
int ans=0;
const int maxn=1e6+10;
int c[maxn];int y[maxn]; 
vector <int> p[1000008];
void fun(int x,int y){
	for(int i=p[x].size()-1;i>=0;i--){
		ans-=(c[p[x][i]-1]==y)+(c[p[x][i]+1]==y);
		
	}
	for(int i=p[x].size()-1;i>=0;i--)
	{
		c[p[x][i]]=y;p[y].push_back(p[x][i]);
	}
	p[x].clear();
}
int main()
{
	int n,m;scanf("%d%d",&n,&m);
	
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&c[i]);
		y[c[i]]=c[i];
		p[c[i]].push_back(i);
		if(c[i]!=c[i-1])	ans++;
	}
	int t1,t2,t3;
	while(m--)
	{
		scanf("%d",&t1);
		if(t1==2)	printf("%d\n",ans);
		else{
			scanf("%d%d",&t2,&t3);
			if(t2==t3)	continue;
			if(p[y[t2]].size()>p[y[t3]].size())	swap(y[t2],y[t3]);
			if(p[y[t2]].size())	fun(y[t2],y[t3]);
		}
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 102ms, 内存消耗: 8924K, 提交时间: 2020-04-12 15:45:09

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,ans,b[N],a[N],c[N],p[N],h[N];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
    	scanf("%d",&a[i]);
    	b[a[i]]=a[i],c[a[i]]++;
    	p[i]=h[a[i]],h[a[i]]=i;
    	if(a[i]!=a[i-1])ans++;
	}
    for(int i=1;i<=m;i++){
    	int f,x,y;
		scanf("%d",&f);
		if(f==1){
			scanf("%d%d",&x,&y);
			if(x==y)continue;
			if(c[b[x]]>c[b[y]])swap(b[x],b[y]);
			x=b[x],y=b[y];
			for(int j=h[x];j;j=p[j]){
				if(a[j+1]==y)ans--;
				if(a[j-1]==y)ans--;
			}
			int k;
			for(int j=h[x];j;j=p[j])a[j]=y,k=j;
			if(h[x])p[k]=h[y],h[y]=h[x];
			c[y]+=c[x],h[x]=c[x]=0;
		}
		else{
			printf("%d\n",ans);
		}
	}
    return 0;
}

上一题