这是一道神奇的题目,我调了大概一天多吧

首先hack一下翻译,操作3并没有要求查询后从其所在集合里删除该元素

于是我们来看一下这三个操作

第一个合并属于并查集的常规操作

第三个操作加权并查集也是可以解决的

至于第二个操作就是这个题的难点了

对于操作二的要求“ 将 \(p\) 移动至包含 \(q\) 的集合中,如果 \(p\) 和 \(q\) 已经在一个集合中,忽视此项操作”,我们可以发现这个操作其实隐含了一个删除的操作,即先从原集合中将 \(p\)删除,再将其移动到集合\(q\)中

我们知道并查集是并不支持删除操作的,于是我们必须对于这个毁天灭地的操作二想出一些奇技淫巧

于是呢,对于操作二,我们可以用一个虚点来代替那个要被从某个集合中删除的点,我们使这个虚点继承这个要被删除的点的所有状态,比如说元素和、元素个数和他的代表元素是谁,而我们在以后\(find\)里路径压缩时只要遇到以这个被删除的点为代表元素的元素,我们把他们的代表元素更新成这个虚点就好了

至于我们如何在路径压缩里判断这个点是否已经被从被某个虚点代替,这里就是真·奇技淫巧了

或许我们可以用map,但map的一次\(find\)复杂度可是\(O(log_2\ n)\)的,我们,可能只有我在这种多组数据的会t的非常欲仙欲死,于是我们的奇技淫巧就要登场了

它就是unordered_map

这是个什么东西呢,我们都知道map是用红黑树实现的,所以map内部\(key\)是有序的,但这也导致我们查询一个元素是否存在是要\(O(log_2\ n)\)的

而这个unordered_map,是c++ 11的新特性,是一个\(key\)无序的map,其内部是用哈希表实现的,单次查询的复杂度可以达到\(O(1)\)的

于是就是代码了

#include<iostream>
#include<map>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<tr1/unordered_map>
//unordered_map所需的头文件,同时在命名空间里加::tr1
#define re register
#define maxn 100001
#define gc getchar
using namespace std::tr1;
using namespace std;
unordered_map<int,int> s;
int fa[maxn<<2],tot[maxn<<2],sum[maxn<<2];
//因为我们虚点的是要用到n+1,n+2...的,所以多开几倍空间
int n,m;
inline int read()
{
char c=gc();
int dx=0;
while(c<'0'||c>'9') c=gc();
while(c>='0'&&c<='9')
dx=(dx<<3)+(dx<<1)+c-48,c=gc();
return dx;
}
int find(int x)
{
if(x==fa[x]) return fa[x];
if(s.count(fa[x])) fa[x]=s[fa[x]];
//如果一个元素的代表元素已经被删除了,那么我们就把它的代表元素换成其映射的那个虚点
return fa[x]=find(fa[x]);
}
void write(int x)
{
if(x>9) write(x/10);
putchar(x%10+48);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)//多组数据标配
{
s.clear();
for(re int i=1;i<=n;i++)
fa[i]=sum[i]=i,tot[i]=1;
while(m--)
{
int p=read();
if(p==1)
{
int xx=find(read());
int yy=find(read());
if(xx==yy) continue;
tot[xx]+=tot[yy];
sum[xx]+=sum[yy];
fa[yy]=xx;
tot[yy]=sum[yy]=0;//常规合并操作
}
if(p==2)
{
int x=read();
int xx=find(x);
int yy=find(read());
if(xx==yy) continue;
if(fa[x]==x&&tot[x]==1)
{
tot[x]=0;
sum[x]=0;
fa[x]=yy;
tot[yy]+=1;
sum[yy]+=x;
continue;
}//如果这个元素代表元素是它自己,且元素个数为1,那它就不可能是其他元素的代表元素,于是我们直接fa[x]=yy就好了
if(s.find(x)==s.end())
{
s[x]=++n;
if(xx==x) fa[n]=n;
else fa[n]=xx;//如果这个元素代表元素是它自己,那么虚点继承这个状态的时候,让虚点的代表元素也是它自己就好了
tot[n]=tot[xx]-1;
sum[n]=sum[xx]-x;
tot[yy]+=1;
sum[yy]+=x;//向新集合添加x
tot[xx]-=1;
sum[xx]-=x;//从原集合中删除x
if(xx==x) sum[xx]=tot[xx]=0;
fa[x]=yy;
}else fa[x]=yy,sum[xx]-=x,tot[xx]-=1,tot[yy]+=1,sum[yy]+=x;
//如果这个元素已经被映射过了,即它已经被加入某一个集合,所以这个时候它不可能成为代表元素,于是这个时候我们也可以直接进行删除和合并的操作
}
if(p==3)
{
int xx=find(read());
write(tot[xx]),putchar(' '),write(sum[xx]);
putchar(10);
}
}
}
return 0;
}

UVA11987 【Almost Union-Find】的更多相关文章

  1. 【机器学习Machine Learning】资料大全

    昨天总结了深度学习的资料,今天把机器学习的资料也总结一下(友情提示:有些网站需要"科学上网"^_^) 推荐几本好书: 1.Pattern Recognition and Machi ...

  2. 一篇文章让Oracle程序猿学会MySql【未完待续】

    一篇文章让Oracle DB学会MySql[未完待续] 随笔前言: 本篇文章是针对已经能够熟练使用Oracle数据库的DB所写的快速学会MySql,为什么敢这么说,是因为本人认为Oracle在功能性方 ...

  3. 【转】【技术博客】Spark性能优化指南——高级篇

    http://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651745207&idx=1&sn=3d70d59cede236e ...

  4. 【windows核心编程】一个API拦截的例子

    API拦截 修改PE文件导入段中的导入函数地址 为 新的函数地址 这涉及PE文件格式中的导入表和IAT,PE文件中每个隐式链接的DLL对应一个IMAGE_IMPORT_DESCRIPTOR描述符结构, ...

  5. 【百度地图API】多家地图API内存消耗对比测验(带源码)

    原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...

  6. 【Spark调优】大表join大表,少数key导致数据倾斜解决方案

    [使用场景] 两个RDD进行join的时候,如果数据量都比较大,那么此时可以sample看下两个RDD中的key分布情况.如果出现数据倾斜,是因为其中某一个RDD中的少数几个key的数据量过大,而另一 ...

  7. (转)【面试】【MySQL常见问题总结】【03】

    [常见面试问题总结目录>>>] [面试][MySQL常见问题总结][03] 2016-05-29 22:20 阅读(8244) 评论(2) [面试][MySQL常见问题总结][02] ...

  8. 【Python之路】第二十篇--MySQL(二)

    视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名], 用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. 1.创建视图 --格式:CREATE ...

  9. 【vim环境配置】详细实录

    [写在前面] 以下的所有内容主要参照: https://github.com/yangyangwithgnu/use_vim_as_ide . 原blog作者写的非常用心,建议大家都去看看.(个人觉得 ...

  10. 【并查集】关押罪犯(BSOJ2809)

    Description S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整 ...

随机推荐

  1. 【转】mvc

    又看到有人在问三层架构和MVC的关系,感觉这种问题有点教条化了.因为它们都在逻辑上将应用程序划为三块,凑了一个数字3,就有人非要把它们联系到一起了. 这两个东西我接触有几年了,有一点体会,表达一下: ...

  2. (微信小程序)二 : 创建一个页面

    首先先看一下pages的目录结构吧. 我创建了一个topics页面.3个文件全创建好了之后 我往topics.js添加数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  3. Charles破解(转)

    NB的Charles是一款付费软件.但…本文将讲解如何破解Charles.注:虽然与文章内容相悖,但还是希望大家能购买正版软件,毕竟都是做软件开发的,何必自断生路,要有版权意识. 环境信息: Mac ...

  4. input的属性用法介绍

    Input表示Form表单中的一种输入对象,其又随Type类型的不同而分文本输入框,密码输入框,单选/复选框,提交/重置按钮等,下面一一介绍. 1,type=text 输入类型是text,这是我们见的 ...

  5. Mac下使用Parallels Desktop安装CentOS操作系统

    Mac下安装Centos后,Mac和Centos之间默认是不通的,需要做下面一些设置后,才能互相共享. 启用网络设置 默认的网络设置是没有enable的,因此,在安装完之后需要开启的话,需要保证开启& ...

  6. centos安装后,连接不上网络,yum命令执行can not find a valid baseurl for repo: base/7/x86-64

    检查了网络适配器是NAT模式没问题,按照网友的方法成功解决: 1.vi /etc/sysconfig/network-scripts/ifcfg-ens123(不是每个主机都是ens123)  把ON ...

  7. [C]逗号运算符

    https://baike.baidu.com/item/%E9%80%97%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6/7959271?fr=aladdin

  8. SASS和SCSS标签详解与scoped局部和全局的使用

    首先,学会使用sass: 1.先下载和安装node-sass和一些加载器 $ cnpm install sass-loader node-sass vue-style-loader --D 2.配置w ...

  9. Python基础-I/O模型

    一.I/O模型 IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接 ...

  10. SpringBoot2.0+Mybatis+PageHelper+Redis实现缓存

    1.在maven引入相关的依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactI ...