orz TPLY 巨佬,题解讲的挺好的。

这里重点梳理一下思路,做一个小小的补充吧。

写可持久化线段树,叶子节点维护每个位置的fa,利用每次只更新一个节点的特性,每次插入\(logN\)个节点,这一部分思路还是很轻松。关于此部分的其它问题可以参考下我的可持久化线段树总结

一开始,写惯了常规并查集、用惯了路径压缩的我,以为在这一题里也要这么搞。我对我的naive真是太感动了

试想一下,因为路径压缩时,再次调用getf后,是要更新一部分值的。在数组上搞这些操作倒是挺快,然而在可持久化线段树里呢?每次找一个fa要\(log\)次,把这个节点更新又要新建log个节点,一共要循环找不满log次,理论上时间复杂度是\(O(Mlog^2N)\)的,但空间也是O\((Mlog^2N)\)的啊,乘个系数\((Mlog^2N×sizeof(int)×4\approx 800MB\),实际不满\()\),随便算算就要炸空间了。。。。。。

那怎么办?去掉路径压缩不就得啦!并查集的按秩合并也是很优秀的方法,每次getf也只需要\(log\)次!时间复杂度\(O(Mlog^2N)\)并没有变。然后每次合并时只需要更新一个点,空间不就省下来了么?空间复杂度\(O(MlogN)\)。

以下是代码,数组版,叶子节点信息用结构体放了一下,略省点空间吧。。。

太弱了,不会封装,非递归版,可能略丑,见谅

#include<cstdio>
#define R register int
#define gc while(*++p<'0')
#define in(z) gc;z=*p&15;while(*++p>='0')z*=10,z+=*p&15
#define copy(id) lc[rt[i]=++cnt]=lc[rt[id]],rc[cnt]=rc[rt[id]];
//直接复制版本,不做改动
const int N=200009,M=4000009;
char I[M];
int n,i,cnt,cntl,rt[N],lc[M],rc[M],pos[M];
//cnt线段树节点,cntl叶子节点,pos记录对应叶子节点在数组中的位置
struct LEAF{
int fa,dep;
}leaf[N<<2];//叶子节点信息,dep用于按秩合并
inline LEAF*getf(R k){
R u,l,r,m;
while(1){
u=rt[i-1],l=1,r=n;
while(l<r)
{
m=(l+r)>>1;
if(k<=m)r=m,u=lc[u];
else l=m+1,u=rc[u];
}
if(k==leaf[pos[u]].fa)break;
k=leaf[pos[u]].fa;//循环找fa
}
return&leaf[pos[u]];//返回指针方便后续操作
}
void build(R&u,R l,R r){//建初始线段树
u=++cnt;
if(l==r){
leaf[pos[u]=++cntl]=(LEAF){l,0};
return;
}
R m=(l+r)>>1;
build(lc[u],l,m),build(rc[u],m+1,r);
}
inline void insert(R*u,R v,R k,LEAF newl){//更新节点
R l=1,r=n,m;
while(l<r) {
*u=++cnt;
m=(l+r)>>1;
if(k<=m)r=m,rc[*u]=rc[v],u=&lc[*u],v=lc[v];
else l=m+1,lc[*u]=lc[v],u=&rc[*u],v=rc[v];
}
leaf[pos[*u=++cnt]=++cntl]=newl;
}
int main(){
fread(I,1,sizeof(I),stdin);
register char*p=I-1;
register LEAF*af,*bf,*tmp;
R m,a,b;
in(n);in(m);
build(rt[0],1,n);
for(i=1;i<=m;++i){
gc;
switch(*p){
case '1':in(a);in(b);
af=getf(a),bf=getf(b);
if(af->fa==bf->fa){copy(i-1);break;}//已合并,跳过操作
if(af->dep>bf->dep)tmp=af,af=bf,bf=tmp;//按秩合并,确定bf为深度更大的
insert(&rt[i],rt[i-1],af->fa,(LEAF){bf->fa,af->dep});
if(af->dep==bf->dep)insert(&rt[i],rt[i],bf->fa,(LEAF){bf->fa,bf->dep+1});//注意更新深度
break;
case '2':in(a);copy(a);break;
case '3':in(a);in(b);copy(i-1);
putchar((getf(a)->fa==getf(b)->fa)|'0');
putchar('\n');
}
}
return 0;
}

洛谷P3402 【模板】可持久化并查集(可持久化线段树,线段树)的更多相关文章

  1. [bzoj] 3673 3674 可持久化并查集 || 可持久化数组

    原题 加强版 题意: 可持久化并查集模板-- 题解: 用可持久化线段树维护一个可持久化数组,来记录每一次操作后的状态. 不能用路径压缩,但是要按置合并,使复杂度保证在O(log) #include&l ...

  2. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  3. bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)

    Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… ...

  4. 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树

    [BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...

  5. Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)

    题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...

  6. 洛谷1525 关押罪犯NOIP2010 并查集

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

  7. 洛谷P1525 关押罪犯(并查集、二分图判定)

    本人蒟蒻,只能靠题解AC,看到大佬们的解题思路,%%%%%% https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着N名罪犯,编 ...

  8. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  9. 洛谷 P1111 修复公路 Label:并查集

    题目背景 A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数N,和公路数M,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你什么时 ...

  10. 洛谷P1955 程序自动分析 [NOI2015] 并查集

    正解:并查集+离散化 解题报告: 传送门! 其实题目还挺水的,,,但我太傻逼了直接想挂了,,,所以感觉还是有个小坑点所以还是写个题解记录下我的傻逼QAQ 首先这题一看,就长得很像NOIp关押罪犯?然后 ...

随机推荐

  1. php使用file_get_contents请求微信接口失败

    windows下的php,只需要到php.ini中把extension=php_openssl.dll前面的;删掉,重启服务就可以了.Linux下的PHP,就必须安装openssl模块,安装好了以后就 ...

  2. php正则判断字符串是否含有中文

    <?php $str = '若你安好便是晴天'; if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $str)>0) { echo '全是中文'; } ...

  3. 深入cocos2d-x中的touch事件

    深入cocos2d-x中的touch事件 在文章cocos2d-x中处理touch事件中简单讨论过怎样处理touch事件, 那么今天来深入了解下cocos2d-x中是怎样分发touch事件的. 我们最 ...

  4. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  5. [HNOI2009] 梦幻布丁

    [HNOI2009] 梦幻布丁 标签: 链表 题解 可以直接用链表启发式合并做. 合并的细节处理稍微有点麻烦. 假如需要变成另一种颜色的那个颜色的个数更多,那么就肯定不能直接合. 维护一个color数 ...

  6. Spring-Security自定义登录页&inMemoryAuthentication验证

    Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架.框架下内容比较多,可以做到按照角色权限对请求路径进行限制.今天主要验证自定义登录页,在内存用户存储中进行请求 ...

  7. Yii2中JSONP跨域问题的解决

    Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据. 为什么我们从不同的域(网站)访问数据需 ...

  8. Ecshop中transport和jquery不兼容的解决方案

    1.修改文件:/js/transport.js,在最底部增加代码 if (Object.prototype.toJSONString){ var oldToJSONString = Object.to ...

  9. 浙江省赛 C What Kind of Friends Are You?

    思路:一开始考虑n个朋友可以有c种可能,根据回答的问题,如果是yes那么可以确定一些朋友的范围,将原本不在这个范围内的删除即可:如果是"no",说明这些朋友都应该被删除,那么最后看 ...

  10. 前端JS面试题汇总 Part 3 (宿主对象与原生对象/函数调用方式/call与apply/bind/document.write)

    原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questio ...