UVA11987 【Almost Union-Find】
这是一道神奇的题目,我调了大概一天多吧
首先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】的更多相关文章
- 【机器学习Machine Learning】资料大全
昨天总结了深度学习的资料,今天把机器学习的资料也总结一下(友情提示:有些网站需要"科学上网"^_^) 推荐几本好书: 1.Pattern Recognition and Machi ...
- 一篇文章让Oracle程序猿学会MySql【未完待续】
一篇文章让Oracle DB学会MySql[未完待续] 随笔前言: 本篇文章是针对已经能够熟练使用Oracle数据库的DB所写的快速学会MySql,为什么敢这么说,是因为本人认为Oracle在功能性方 ...
- 【转】【技术博客】Spark性能优化指南——高级篇
http://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651745207&idx=1&sn=3d70d59cede236e ...
- 【windows核心编程】一个API拦截的例子
API拦截 修改PE文件导入段中的导入函数地址 为 新的函数地址 这涉及PE文件格式中的导入表和IAT,PE文件中每个隐式链接的DLL对应一个IMAGE_IMPORT_DESCRIPTOR描述符结构, ...
- 【百度地图API】多家地图API内存消耗对比测验(带源码)
原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...
- 【Spark调优】大表join大表,少数key导致数据倾斜解决方案
[使用场景] 两个RDD进行join的时候,如果数据量都比较大,那么此时可以sample看下两个RDD中的key分布情况.如果出现数据倾斜,是因为其中某一个RDD中的少数几个key的数据量过大,而另一 ...
- (转)【面试】【MySQL常见问题总结】【03】
[常见面试问题总结目录>>>] [面试][MySQL常见问题总结][03] 2016-05-29 22:20 阅读(8244) 评论(2) [面试][MySQL常见问题总结][02] ...
- 【Python之路】第二十篇--MySQL(二)
视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名], 用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. 1.创建视图 --格式:CREATE ...
- 【vim环境配置】详细实录
[写在前面] 以下的所有内容主要参照: https://github.com/yangyangwithgnu/use_vim_as_ide . 原blog作者写的非常用心,建议大家都去看看.(个人觉得 ...
- 【并查集】关押罪犯(BSOJ2809)
Description S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整 ...
随机推荐
- WEB下渗透测试经验技巧(全)[转载]
Nuclear’Atk 整理的: 上传漏洞拿shell: 1.直接上传asp.asa.jsp.cer.php.aspx.htr.cdx….之类的马,拿到shell.2.就是在上传时在后缀后面加空格或者 ...
- 获取URL中某个参数的值
JS代码: function getQueryString(name){ var reg = new RegExp("(^|&)" + name + "=([^& ...
- wcf 基本配置
<system.serviceModel> <services> <service name="ServiceUpdater.ServiceUpdate&quo ...
- js扩展
http://www.css88.com/doc/underscore/#findWhere
- Tidb 离线Ansible方式部署实践
1.最近浏览到一个比较新的分布式数据库Tidb,开源看起来比较牛的样子,一时手痒就动手试试部署 2.参考官方 Ansible 离线方式部署 :https://pingcap.com/docs-cn/o ...
- Javaee的Dao层的抽取
有时候我们在实现不同功能的时候回看到很多的Dao层的增加.修改.删除.查找都很相似,修改我们将他们提取BaseDao 一.提取前 1. 提取前的LinkDao层: public interface L ...
- Linux中的叹号命令
在shell环境下操作,需要积累点快捷输入的小技巧: 最常用的技巧恐怕就是Tab自动补全以及上方向键来回退上几条历史命令了,这些对于csh,bash,ksh,zsh都适用. 最近还找到一种快速回退上一 ...
- Hive Join
最近被朋友问到有关于Hive Join的问题,保守回答过后,来补充补充知识: Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能. 一.Hi ...
- javaweb之jsp标签
1.JSP标签简介 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 2.JSP常用标签 ...
- Unknown entity XXX
在jdbc中使用session保存实体的时候,保存出错,Unknown entity XXX 一种解决方案为 http://ningnian169.blog.51cto.com/2417825/450 ...