zoukankan      html  css  js  c++  java
  • 启发式合并训练之一

    以前没怎没接触过,快要考试了,赶快来补一补

    https://www.luogu.org/problem/P3201

    分析:

    将同一种颜色用类似链式前向星的形式存起来

    考虑启发式合并,将小的合并到大的上面

    如果要将x变为y,

    如果sz[x]<sz[y],就直接把x接在y的上面就好

    如果sz[x]>sz[y],如果直接把y接在x后面颜色就会变为x

    所以我们需要使用一个 f数组,表示当我们要寻找颜色 x 时,实际上需要寻找颜色为 f[x] 的链。如果遇到上面这种情况就要交换交换 f[x]和 f[y]。

    code :

    #include<bits/stdc++.h>
    #define ll long long
    #define il inline
    #define ri register int
    #define lowbit(x) x&(-x)
    using namespace std;
    const int maxn=1e6+5;
    int head[maxn],nxt[maxn],fir[maxn];
    int a[maxn],col[maxn],sz[maxn];
    int n,m,ans;
    il void merge(int x,int y){
    	for(ri i=head[x];i;i=nxt[i]){
    		if(a[i-1]==y)ans--;
    		if(a[i+1]==y)ans--;
    	}
    	for(ri i=head[x];i;i=nxt[i])a[i]=y;
    	nxt[fir[x]]=head[y];
    	head[y]=head[x]; 
    	sz[y]+=sz[x];
    	head[x]=sz[x]=fir[x]=0;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(ri 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;
    	   sz[a[i]]++;
    	   nxt[i]=head[a[i]];
    	   head[a[i]]=i;
    	}
    	while(m--){
    		int op,x,y;
    		scanf("%d",&op);
    	   if(op==1){
    		scanf("%d%d",&x,&y);
    		if(x==y)continue;
    		if(sz[col[x]]>sz[col[y]])swap(col[x],col[y]);
    		if(!sz[col[x]])continue;
    		merge(col[x],col[y]);
    	}
    	else printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    java实现HTTP请求 HttpUtil
    java-websocket客户端 断线重连 注入Service问题
    人工智能博客
    git 修改注释
    2019-2-22
    2019-2-21
    2019-2-20
    /与./和../的含义
    第二章(构建有多个房间的聊天室程序)
    第一章(欢迎进入node.js世界)
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11864906.html
Copyright © 2011-2022 走看看