• [HNOI2009]梦幻布丁 启发式链表合并


    因为启发式合并,所以我们强制用长链代表短链,遍历修改短链的所有节点

    由于我们只存储了位置之间是同色的关系形成的链条,这些链条无颜色特征,所以我们把长链分配给新颜色

    即一次swap操作,用fa[x]记录颜色x的在C数组中存储的真实颜色

    其他部分就是水水细节啦。。

    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<iostream>
    #include<math.h>
    using namespace std;
    #define ll long long
    const int maxn=1e6+7;
    const int inf=0x3f3f3f3f;
    #define FOR(n) for(int i=1;i<=n;i++)
    #define pb push_back
    
    int n,m,ans;
    int c[maxn],fa[maxn];
    int size[maxn],head[maxn],nxt[maxn];
    
    void merge(int x,int y){
    	for(int i=head[x];i;i=nxt[i]){
    		if(c[i-1]==y)ans--;
    		if(c[i+1]==y)ans--;
    	}
    	for(int i=head[x];i;i=nxt[i]){
    		c[i]=y;
    		if(!nxt[i]){
    			nxt[i]=head[y],head[y]=head[x];break;
    		}
    	}
    	size[y]+=size[x];head[x]=size[x]=0;
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&c[i]);
    		if(c[i]!=c[i-1])ans++;
    		fa[c[i]]=c[i];
    		nxt[i]=head[c[i]],head[c[i]]=i;
    		size[c[i]]++;
    	}
    	for(int op,x,y,i=1;i<=m;i++){
    		scanf("%d",&op);
    		if(op==2)printf("%d
    ",ans);
    		else{
    			scanf("%d%d",&x,&y);	//	x染色为y
    			if(size[fa[x]]>size[fa[y]])swap(fa[x],fa[y]);
    			x=fa[x],y=fa[y];
    			if(x==y || size[x]==0)continue;
    			merge(x,y);
    		}
    	}
    }


  • 相关阅读:
    多线程
    异常
    接口
    多态
    对象和封装
    DIV+CSS命名规范集合
    MySql 最新官方安装教程-下载
    乐嘉性格色彩-4色特性,学习感悟
    Eclipse 的常用快捷方式
    学习方法_2011年编写和锻炼的思维题
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611263.html
Copyright © 2020-2023  润新知