题目:bzoj3673:https://www.lydsy.com/JudgeOnline/problem.php?id=3673

   bzoj3674:https://www.lydsy.com/JudgeOnline/problem.php?id=3674

   洛谷P3402:https://www.luogu.org/problemnew/show/P3402

可持久化并查集!就是用主席树模拟并查集,真美!

路径压缩版:和并查集的相似之处想想感觉好妙;

但复杂度似乎有点不科学,bzoj 的两道题都能过,但洛谷上的模板过不了;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=2e4+,maxm=3e6+;
//int const maxn=2e5+5,maxm=1e7+5;
int n,m,f[maxm],ls[maxm],rs[maxm],rt[maxn],cnt,ans;
void build(int &x,int l,int r)
{
x=++cnt;
if(l==r){f[x]=l; return;}
int mid=((l+r)>>);
build(ls[x],l,mid); build(rs[x],mid+,r);
}
void insert(int x,int &y,int l,int r,int pos,int val)
{
y=++cnt;
if(l==r){f[y]=val; return;}//不是f[pos]
int mid=((l+r)>>);
ls[y]=ls[x]; rs[y]=rs[x];
if(pos<=mid)insert(ls[x],ls[y],l,mid,pos,val);
else insert(rs[x],rs[y],mid+,r,pos,val);
}
int query(int x,int l,int r,int pos)
{
if(l==r)return f[x];
int mid=((l+r)>>);
if(pos<=mid)return query(ls[x],l,mid,pos);
else return query(rs[x],mid+,r,pos);
}
int find(int &root,int pos)
{
int tmp=query(root,,n,pos);
if(tmp==pos)return pos;
int ret=find(root,tmp);
insert(root,root,,n,pos,ret);//路径压缩,修改root
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
build(rt[],,n);
for(int i=,op,k,x,y;i<=m;i++)
{
scanf("%d",&op);
if(op==)
{
scanf("%d%d",&x,&y);
// x^=ans; y^=ans;
int fx=find(rt[i-],x),fy=find(rt[i-],y);
if(fx==fy)rt[i]=rt[i-];
else insert(rt[i-],rt[i],,n,fx,fy);
}
if(op==)
{
scanf("%d",&k);
// k^=ans;
rt[i]=rt[k];
}
if(op==)
{
scanf("%d%d",&x,&y);
// x^=ans; y^=ans;
int fx=find(rt[i-],x),fy=find(rt[i-],y);
if(fx==fy)ans=,printf("1\n");
else ans=,printf("0\n");
rt[i]=rt[i-];
}
}
return ;
}

按秩合并版:复杂度科学,写起来也很简洁,洛谷模板能过;

感觉数据结构写好了模板摆在那儿什么都能干,很方便啊。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=2e5+,maxm=1e7+;
int n,m,f[maxm],ls[maxm],rs[maxm],dep[maxm],rt[maxn],cnt,ans;
void build(int &x,int l,int r)
{
x=++cnt;
if(l==r){f[x]=l; dep[x]=; return;}
int mid=((l+r)>>);
build(ls[x],l,mid); build(rs[x],mid+,r);
}
void insert(int x,int &y,int l,int r,int pos,int val)
{
y=++cnt;
if(l==r){f[y]=val; dep[y]=dep[x]; return;}
int mid=((l+r)>>);
ls[y]=ls[x]; rs[y]=rs[x];
if(pos<=mid)insert(ls[x],ls[y],l,mid,pos,val);
else insert(rs[x],rs[y],mid+,r,pos,val);
}
void add(int x,int &y,int l,int r,int val)
{
y=++cnt;
if(l==r){f[y]=val; dep[y]=dep[x]+; return;}
int mid=((l+r)>>);
ls[y]=ls[x]; rs[y]=rs[x];
if(val<=mid)add(ls[x],ls[y],l,mid,val);
else add(rs[x],rs[y],mid+,r,val);
}
int query(int x,int l,int r,int pos)
{
if(l==r)return x;
int mid=((l+r)>>);
if(pos<=mid)return query(ls[x],l,mid,pos);
else return query(rs[x],mid+,r,pos);
}
int find(int &root,int pos)
{
int tmp=query(root,,n,pos);
if(f[tmp]==pos)return tmp;
return find(root,f[tmp]);
}
int main()
{
scanf("%d%d",&n,&m);
build(rt[],,n);
for(int i=,op,k,x,y;i<=m;i++)
{
scanf("%d",&op);
if(op==)
{
scanf("%d%d",&x,&y);
int fx=find(rt[i-],x),fy=find(rt[i-],y);
if(f[fx]==f[fy]){rt[i]=rt[i-]; continue;}
if(dep[fx]>dep[fy])swap(fx,fy);
insert(rt[i-],rt[i],,n,f[fx],f[fy]);
if(dep[fx]==dep[fy])add(rt[i],rt[i],,n,f[fy]);//最大深度相等则合并后dep+1
}
if(op==)
{
scanf("%d",&k);
rt[i]=rt[k];
}
if(op==)
{
scanf("%d%d",&x,&y);
int fx=find(rt[i-],x),fy=find(rt[i-],y);
if(fx==fy)ans=,printf("1\n");
else ans=,printf("0\n");
rt[i]=rt[i-];
}
}
return ;
}

bzoj3673 & bzoj3674 & 洛谷P3402 可持久化并查集的更多相关文章

  1. 洛谷P3402 可持久化并查集

    n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 说是可持久化并查集,实际上是 ...

  2. BZOJ3673 & BZOJ3674 & 洛谷3402:可持久化并查集——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3673 https://www.lydsy.com/JudgeOnline/problem.php? ...

  3. P3402 可持久化并查集

    P3402 通过主席树维护不同版本的并查集,注意要采用按秩合并的方式,路径压缩可能会爆. 1 #include <bits/stdc++.h> 2 using namespace std; ...

  4. 洛谷 3295 [SCOI2016]萌萌哒——并查集优化连边

    题目:https://www.luogu.org/problemnew/show/P3295 当要连的边形如 “一段区间内都是 i 向 i+L 连边” 的时候,用并查集优化连边. 在连边的时候,如果要 ...

  5. 洛谷P2024 食物链 [NOI2001] 并查集

    正解:并查集 解题报告: 传送门(咕了! 其实没有很难(虽然我是交了三发才过的QAQ 但是一来好久没打并查集了恢复一下智力 二来看着智推里唯一一个蓝就很不爽(,,,虽然做了这题之后又补上了个蓝题QAQ ...

  6. 洛谷P1197 [JSOI2008] 星球大战 [并查集]

    题目传送门 星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这 ...

  7. 洛谷 P1551 亲戚(并查集模板)

    嗯... 题目链接:https://www.luogu.org/problemnew/show/P1551 思路: 很显然地我们会发现,这是一道并查集的模板题,并且是考察了并查集中的”并“和”查“的操 ...

  8. 洛谷P1111修复公路并查集改

    看了他们的题解感觉很震惊,为什么要用kruskal,这题要用到最小生成树吗??? 38行短短的程序就可以了,我觉得学习不是一种套用,套自己学的,而且题解很大一部分都是kruskal. 个人认为自己的程 ...

  9. 洛谷P1525关押罪犯——并查集

    题目:https://www.luogu.org/problemnew/show/P1525 并查集+贪心,从大到小排序,将二人分在不同房间,找到第一个不满足的即为答案. 代码如下: #include ...

随机推荐

  1. 在CentOS6,CentOS7安装 Let'sEncrypt 免费SSL安全证书

    相对来说,个人网站建立SSL是昂贵的,而且往往过程繁琐.一个标准的2048位证书费用至少150美元/年,网站除了要支付一笔昂贵的费用.重新配置Web服务器,并需要解决大量的配置错误.这让广大中小网站望 ...

  2. (二)Python 学习第二天--爬5068动漫图库小案例

    (注:代码和网站仅仅是学习用途,非营利行为,源代码参考网上大神代码,仅仅用来学习

  3. 配置本地git服务器(gitblit win7)

    title: 配置本地git服务器 date: 2017年3月7日22:43:14 gitblit(不用安装) 进入gitblit-1.8.0\data下,编辑gitblit.properties和d ...

  4. unittest 是什么?怎么用?

    unittest单元测试框架详解 https://www.cnblogs.com/fighter007/p/8245063.html unittest最详细的解说 https://www.cnblog ...

  5. centos 设置 ip地址

    linux设置ip,主要是修改/etc/sysconfig/network-scripts/ifcfg-** 里面的网卡配置文件,然后命令 service network restart 生效 自动获 ...

  6. stress工具使用指南和结果分析

    stress介绍 #stress `stress' imposes certain types of compute stress on your system Usage: stress [OPTI ...

  7. 293. [NOI2000] 单词查找树——COGS

    293. [NOI2000] 单词查找树 ★★   输入文件:trie.in   输出文件:trie.out   简单对比时间限制:1 s   内存限制:128 MB 在进行文法分析的时候,通常需要检 ...

  8. Scrapy下载器中间件用法示例

    1.爬虫文件httpbin.py # -*- coding: utf-8 -*- import scrapy class HttpbinSpider(scrapy.Spider): name = 'h ...

  9. Laravel-Action 对代码的改造

    前言 以往写过俩篇文章[积德篇] 如何少写PHP "烂"代码 https://segmentfault.com/a/11...举枪消灭"烂代码"的实战案例 ht ...

  10. 面试题:你能写一个Vue的双向数据绑定吗?

    在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...