【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1878 Solved: 846
[Submit][Status][Discuss]
Description
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m<=2*10^4
Input
Output
Sample Input
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
0
1
HINT
Source
3674: 可持久化并查集加强版
Time Limit: 15 Sec Memory Limit: 256 MB
Submit: 2367 Solved: 886
[Submit][Status][Discuss]
Description
Description:
自从zkysb出了可持久化并查集后……
hzwer:乱写能AC,暴力踩标程
KuribohG:我不路径压缩就过了!
ndsf:暴力就可以轻松虐!
zky:……
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
0<n,m<=2*10^5
Input
Output
Sample Input
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2
Sample Output
0
1
HINT
Source
Solution
先说离线的一种思路,以前yveh做Codeforces的时候告诉我一道题,与之类似,存在一个状态退回到第多少步,当时是需要线段树维护一个东西,所以可以形成一个树形结构,然后dfs并回溯离线做。
但是这里并不能那么搞,因为并查集不支持删除所以没法回溯,所以只能考虑令并查集的 代表元素数组可持久化
所以本质上都得用可持久化数据结构维护代表元素数组,就无所谓离线在线了。
具体的做法就是建可持久化线段树,每次修改就在线段树上建一个新的链,叶子节点维护的是这个点的代表元素,所以方法很简单就是先初始化建出一棵新的树,然后每次新建一条链即可。
然后这里就剩下一个问题了,就是并查集$find$,为了保证复杂度,我采用了路径压缩但这里发现路径压缩会使树上操作数增多,建很多新的节点,所以常数比较大,然后看了hxy和zyf的代码,发现她们都和hzwer写的一样,采用的按秩合并,不过常数比我还大,不过显而易见 如果不加优化一定会TLE,所以二选一即可,并无太大的差距。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 500010
int N,M,last;
namespace PrTree
{
int sz,lson[MAXN*],rson[MAXN*],root[MAXN],f[MAXN*];
inline void Insert(int l,int r,int &now,int fa,int pos,int val)
{
now=++sz;
if (l==r) {f[now]=val; return;}
int mid=(l+r)>>;
lson[now]=lson[fa],rson[now]=rson[fa];
if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val);
else Insert(mid+,r,rson[now],rson[fa],pos,val);
}
inline int Query(int l,int r,int pos,int now)
{
if (l==r) return f[now];
int mid=(l+r)>>;
if (pos<=mid) return Query(l,mid,pos,lson[now]);
else return Query(mid+,r,pos,rson[now]);
}
inline void BuildTree(int l,int r,int &now)
{
now=++sz;
if (l==r) {f[now]=l; return;}
int mid=(l+r)>>;
BuildTree(l,mid,lson[now]); BuildTree(mid+,r,rson[now]);
}
}using namespace PrTree;
inline int F(int x,int &rt) {int fa; if ((fa=Query(,N,x,rt))==x) return x; else return Insert(,N,rt,rt,x,fa=F(fa,rt)),fa;}
inline void Merge(int x,int y,int &rt) {int fx=F(x,rt),fy=F(y,rt); if (fx!=fy) Insert(,N,rt,rt,fx,fy);}
int main()
{
N=read(),M=read();
BuildTree(,N,root[]);
for (int i=; i<=M; i++)
{
root[i]=root[i-];
int opt=read(),x,y;
switch (opt)
{
case : x=read(),y=read(); x^=last,y^=last; Merge(x,y,root[i]); break;
case : x=read(); x^=last; root[i]=root[x]; break;
case : x=read(),y=read(); x^=last,y^=last; printf("%d\n",last=(F(x,root[i])==F(y,root[i]))); break;
}
}
return ;
}
总体来说写起来还是蛮好写的,就是自己开始手误,在可持久化线段树的时候 左右都下放的lson,然后瞪着屏幕20分钟才看出来...
【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集的更多相关文章
- [WC2005]双面棋盘(线段树+并查集)
线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...
- 【bzoj4399】魔法少女LJJ 并查集+权值线段树合并
题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味: ...
- 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)
2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...
- bzoj 3673&3674 可持久化并查集&加强版(可持久化线段树+启发式合并)
CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...
- BZOJ.3673/3674.可持久化并查集(可持久化线段树 按秩合并/启发式合并)
BZOJ 3673 BZOJ 3674(加强版) 如果每次操作最多只修改一个点的fa[],那么我们可以借助可持久化线段树来O(logn)做到.如果不考虑找fa[]的过程,时空复杂度都是O(logn). ...
- bzoj 3673&3674: 可持久化并查集 by zky
Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...
- [bzoj] 3673 3674 可持久化并查集 || 可持久化数组
原题 加强版 题意: 可持久化并查集模板-- 题解: 用可持久化线段树维护一个可持久化数组,来记录每一次操作后的状态. 不能用路径压缩,但是要按置合并,使复杂度保证在O(log) #include&l ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】
bzoj上数组开大会T-- 本来想用set瞎搞的,想了想发现不行 总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪 ...
随机推荐
- PHP跨域form提交
因为安全性因素,直接跨域访问是不被允许的. 1.PHP CURL方式 function curlPost($url,$params) { $postData = ''; foreach($params ...
- CSS3和javascript中的transform
在javascript中,WebkitTransform 大概相当于 transform .transform 为标准,WebkitTransform 适用于Webkit浏览器.js中的WebkitT ...
- 【大前端之打通账号系统】passport应该如何落地?
前言 之前接入百度账号系统的时候写了一篇博客做研究:[大前端]认识单点登录,出来后才发现,很多小公司其实并没有将账号系统打通,总结一下账号系统没通的原因是: ① 最初设计就没想过身份认证应该做整合 ② ...
- 针对JS经典题型对全局变量及局部变量的理解浅谈
第一次写博,还蛮激动... 看到了三题经典题型,就我目前的认识对此题进行总结.如有错误,敬请指正 首先,我们先明确一下JS引擎的工作步骤: js引擎工作分为两步: 1.将这个js中的变量和函数声明保存 ...
- Socket--Android王国的外交发言人
Socket:原意"插座",在Java语言中为"套接字" 用于描述IP地址和端口号,是通信链的句柄,我们可以通过它向网络发送请求或者应答网络请求; 它是支持TC ...
- Oracle 用户、角色、权限(系统权限、对象权限)的数据字典表
1 三者的字典表 1.1 用户 select * from dba_users; select * from all_users; select * from user_users; 1.2 角色 s ...
- swfupload 相关配置
部署在IIS上出现404: 修改 C:\Windows\System32\inetsrv\config\applicationHost.config 文件 连续查找requestFiltering,往 ...
- centos7的网络设置
必备知识:linux下对文件的编辑操作 首先给出的是vi的基础 后面会有详细的远程连接Centos的方法 vi的基本概念 基本上vi可分为三种操作状态,分别是命令模式(Command mode).插 ...
- JS--轻松设置获取表单数据
接触过Angularjs的都知道,ng支持双向绑定,我们可以轻轻松松的通过ngModel将我们的值绑定到界面,当修改了值提交表单的时候不需要再重新通过ID去重新抓取输入框信息了.那对于我们开发前台网站 ...
- python下print结果到文件中的方法
目的是将print的结果输出到一个文件中,比如这个文件在D:\lianxi\out.txt下,我用的windows: s = '1234' f = open (r'D:\lianxi\out.txt' ...