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

5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2

Sample Output

1
0
1

Solution

板子题……只不过网上有很多假做法。

具体做法就是整两个可持久化数组(不知道谁起的这么鬼畜的名字……我还是更喜欢叫他可持久化线段树)来记录并查集的$fa$数组和$dep$数组。因为路径压缩会破坏可持久化的结构,所以我们只能记录$dep$数组来按秩合并。

网上很多只搞了一颗可持久化线段树,维护$fa$就可持久化线段树$insert$一条链,维护$dep$就修改历史版本上的点的做法是错的……已经被卡掉了QAQ

Code

 #include<iostream>
#include<cstdio>
#define N (200009)
using namespace std; int n,m,lastans,opt,x,y; struct Tree
{
struct Sgt{int ls,rs,v;}Segt[N*];
int sgt_num,a[N],Root[N];
int Build(int l,int r)
{
int now=++sgt_num;
if (l==r) {Segt[now].v=a[l]; return now;}
int mid=(l+r)>>;
Segt[now].ls=Build(l,mid);
Segt[now].rs=Build(mid+,r);
return now;
}
int Update(int pre,int l,int r,int x,int v)
{
int now=++sgt_num;
Segt[now].ls=Segt[pre].ls;
Segt[now].rs=Segt[pre].rs;
if (l==r) {Segt[now].v=v; return now;}
int mid=(l+r)>>;
if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x,v);
else Segt[now].rs=Update(Segt[now].rs,mid+,r,x,v);
return now;
}
int Query(int now,int l,int r,int x)
{
if (l==r) return Segt[now].v;
int mid=(l+r)>>;
if (x<=mid) return Query(Segt[now].ls,l,mid,x);
else return Query(Segt[now].rs,mid+,r,x);
}
}CT[]; int Find(int x,int t)
{
int fa=CT[].Query(CT[].Root[t],,n,x);
return x==fa?x:Find(fa,t);
} int main()
{
scanf("%d%d",&n,&m);
for (int i=; i<=n; ++i)
CT[].a[i]=i, CT[].a[i]=;
CT[].Root[]=CT[].Build(,n);
CT[].Root[]=CT[].Build(,n);
for (int i=; i<=m; ++i)
{
scanf("%d",&opt);
if (opt==)
{
CT[].Root[i]=CT[].Root[i-];
CT[].Root[i]=CT[].Root[i-];
scanf("%d%d",&x,&y);
/*x^=lastans; y^=lastans;*/
int fx=Find(x,i),fy=Find(y,i);
if (fx==fy) continue;
int dfx=CT[].Query(CT[].Root[i],,n,fx);
int dfy=CT[].Query(CT[].Root[i],,n,fy);
if (dfx>dfy) swap(fx,fy);
CT[].Root[i]=CT[].Update(CT[].Root[i],,n,fx,fy);
if (dfx!=dfy) continue;
CT[].Root[i]=CT[].Update(CT[].Root[i],,n,fy,dfy+);
}
if (opt==)
{
scanf("%d",&x); /*x^=lastans;*/
CT[].Root[i]=CT[].Root[x];
CT[].Root[i]=CT[].Root[x];
}
if (opt==)
{
CT[].Root[i]=CT[].Root[i-];
CT[].Root[i]=CT[].Root[i-];
scanf("%d%d",&x,&y);
/*x^=lastans; y^=lastans;*/
int fx=Find(x,i),fy=Find(y,i);
if (fx==fy) puts("")/*, lastans=1*/;
else puts("")/*, lastans=0*/;
}
}
}

BZOJ3673/3674:可持久化并查集的更多相关文章

  1. [BZOJ3673&3674]可持久化并查集&加强版

    题目大意:让你实现一个可持久化的并查集(3674强制在线). 解题思路:刚刚介绍了一个叫rope的神器:我是刘邦,在这两题(实际上两题没什么区别)就派上用场了. 正解应该是主席树||可持久化平衡树,然 ...

  2. [bzoj3673/3674可持久化并查集加强版]

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

  3. BZOJ 3674 可持久化并查集加强版(路径压缩版本)

    /* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...

  4. BZOJ 3674 可持久化并查集加强版(按秩合并版本)

    /* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...

  5. 【BZOJ】3673: 可持久化并查集 by zky & 3674: 可持久化并查集加强版(可持久化线段树)

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

  6. bzoj 3673&3674 可持久化并查集&加强版(可持久化线段树+启发式合并)

    CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...

  7. BZOJ 3674 可持久化并查集加强版(主席树变形)

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 2515  Solved: 1107 [Submit][Sta ...

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

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

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

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

随机推荐

  1. C++11 Lambda表达汇总总结

    C++ 11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作.Lambda的语法形式如下:               [函数对象参数] (操作符重载函数参数) mutable或ex ...

  2. 微信支付 统一下单 字段 body 为中文时 报【签名错误】解决方案(C# SDK)

    方案一 如果你是从微信支付官网下载的 .NET C#[微信支付]API对应的SDK 调用示例 查看源码,会发现这个SDK中的 WxPayData 的类的 CalcHMACSHA256Hash 签名方法 ...

  3. [EWS]查找 文件夹

    摘要 有时在操作exchange的时候,需要查找用户exchange文件夹,比如用户新建了一些文件夹. 一个例子 这里以查找用户outlook邮箱中的历史对话文件夹为例. private const ...

  4. 链接正常但IE浏览器无法显示网页的几种情况

    一.感染病毒木马所致 这种情况往往表现在打开IE时,在IE界面的左下框里提示:正在打开网页,但一直无响应. 右击任务栏/任务管理器/进程,查看.如果CPU占用率100%,可以断定是感染了病毒,这时要查 ...

  5. Java并发编程-移相器

    移相器(Phaser)内有2个重要状态,分别是phase和party.phase就是阶段,初值为0,当所有的线程执行完本轮任务,同时开始下一轮任务时,意味着当前阶段已结束,进入到下一阶段,phase的 ...

  6. swagger2的使用

    springboot项目里怎么使用swagger2? 1.maven依赖 <dependency> <groupId>io.springfox</groupId> ...

  7. Java - "JUC" ReentrantLock获取锁

    [Java并发编程实战]-----“J.U.C”:ReentrantLock之一简介 ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”. 顾名思义,R ...

  8. -C++11可变模版参数(转载)

    泛化之美--C++11可变模版参数的妙用 1概述 C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意 ...

  9. 华中农业大学第五届程序设计大赛网络同步赛-A

    Problem A: Little Red Riding Hood Time Limit: 1 Sec  Memory Limit: 1280 MBSubmit: 860  Solved: 133[S ...

  10. openstack-on-centos7之环境准备

    centos7配置静态ip ifconfig查看网卡信息并获取到网卡的名称eth0s3 ifconfig 进入到网卡配置目录 cd /etc/sysconfig/network-scripts/ 找到 ...