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.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整 ...
随机推荐
- Silverlight & Blend动画设计系列七:模糊效果(BlurEffect)与阴影效果(DropShadowEffect)
模糊效果(BlurEffect)与阴影效果(DropShadowEffect)是两个非常实用和常用的两个特效,比如在开发相册中,可以对照片的缩略图添加模糊效果,在放大照片的过程中动态改变照片的大小和模 ...
- C#语言-05.委托和事件
a. 委托:是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联.所谓兼容的方法,是指这个方法和委托的方法签名具有相同的返回类型和参数 i. 语法:delegate 方法签名; . 方法签名是方 ...
- asp.net Core2.1连接到Mysql 数据库
1.首先,安装相关插件 在nuget下安装 1.Pomelo.EntityFrameworkCore.MySql 2.MySql.Data.EntityFrameworkCore 都要是2.1 < ...
- Asp.NET MVC4 + Ajax 实现多文件上传
本文转自http://www.cnblogs.com/freeliver54/archive/2013/05/15/3079700.html JS部分测试可以,jQuery部分没有测试先留着 HTML ...
- GeneratedKeyHolder的作用:获得新建主键值
Spring利用GeneratedKeyHolder,提供了一个可以返回新增记录对应主键值的方法: int update(PreparedStatementCreator psc, KeyHolder ...
- 改善Java程序的151个建议(1-4)
1.不要在常量和变量中出现易混淆的数字 个人感觉这条在于编程命名的规范性.代码除了给机器看,也要给人看.要写能够结构清晰,命名规范,让人看懂的代码. 字母l作为长整型标志时务必大写 L 2.莫让常量蜕 ...
- 第一行代码 10.2使用HTTP协议访问网络 HttpURLConnection代码中的问题
实现HttpURLConnection代码的时候,遇到了问题. 怎样点击途中Send Request按钮,没有任何改变. 最后将MainActivity中的一段代码URL url = new URL( ...
- BootStrap:
BootStrap: * 响应式的HTML,CSS,JS的框架. * 响应式设计: * 设计一套页面,适配不同的设备,在手机,PAD,PC端都能够正常浏览. * 响应式原理: * 使用CSS3的媒体查 ...
- 为什么canvas宽高要设置在标签内>>宽高设置在style和设置在canvas的区别
一直很困惑为什么canvas标签和其他标签不一样,宽高需要设置在canvas标签里,设置在style里就会有问题. 纯粹个人理解,有错误欢迎指出. > 结论写在头 设置在style里有问题其实是 ...
- bootstrap-datepicker汉化
bootstrap-datepicker 是一个非常优秀的时间选择插件,默认是英文显示日期的,通过下面几个小修改让其支持默认中文 1.首先将 bootstrap-datepicker.js 另存为 u ...