题解

感觉全世界都写过只有我没写过

毕竟是板子还是挺简单的,只要用可持久化线段树维护一下数组的形态就好了,每个数组里面维护这个数组的father,和这个点所在树的最长链的深度(如果这个点是根按秩合并要用)

为了避免返回两个值可以直接返回所在线段树节点的编号

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <bitset>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define MAXN 200005
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
} int N,M;
struct node {
int f,dep,lc,rc;
}tr[MAXN * 80];
int rt[MAXN],Ncnt;
void build(int &u,int l,int r) {
u = ++Ncnt;
if(l == r) {
tr[u].f = l;
tr[u].dep = 1;
return;
}
int mid = (l + r) >> 1;
build(tr[u].lc,l,mid);
build(tr[u].rc,mid + 1,r);
}
int Query(int u,int L,int R,int pos) {
if(L == R) return u;
int mid = (L + R) >> 1;
if(pos <= mid) return Query(tr[u].lc,L,mid,pos);
else return Query(tr[u].rc,mid + 1,R,pos);
}
void Change(int x,int &y,int L,int R,int pos,int v) {
y = ++Ncnt;
tr[y] = tr[x];
if(L == R) {tr[y].f = v;return;}
int mid = (L + R) >> 1;
if(pos <= mid) Change(tr[x].lc,tr[y].lc,L,mid,pos,v);
else Change(tr[x].rc,tr[y].rc,mid + 1,R,pos,v);
}
void Inc_dep(int x,int &y,int L,int R,int pos) {
y = ++Ncnt;
tr[y] = tr[x];
if(L == R) {tr[y].dep++;return;}
int mid = (L + R) >> 1;
if(pos <= mid) Inc_dep(tr[x].lc,tr[y].lc,L,mid,pos);
else Inc_dep(tr[x].rc,tr[y].rc,mid + 1,R,pos);
}
int getfa(int u,int x) {
int p = Query(u,1,N,x);
if(tr[p].f == x) return p;
else return getfa(u,tr[p].f);
}
void Solve() {
read(N);read(M);
build(rt[0],1,N);
int op,a,b;
for(int i = 1 ; i <= M ; ++i) {
read(op);
if(op == 1) {
rt[i] = rt[i - 1];
read(a);read(b);
a = getfa(rt[i],a);b = getfa(rt[i],b);
if(a == b) continue;
if(tr[a].dep < tr[b].dep) Change(rt[i],rt[i],1,N,tr[a].f,tr[b].f);
else if(tr[b].dep < tr[a].dep) Change(rt[i],rt[i],1,N,tr[b].f,tr[a].f);
else {
Change(rt[i],rt[i],1,N,tr[a].f,tr[b].f);
Inc_dep(rt[i],rt[i],1,N,tr[b].f);
}
}
else if(op == 2) {
read(a);
rt[i] = rt[a];
}
else if(op == 3) {
rt[i] = rt[i - 1];
read(a);read(b);
a = getfa(rt[i],a);b = getfa(rt[i],b);
if(a == b) {puts("1");}
else puts("0");
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}

【BZOJ】3674: 可持久化并查集加强版的更多相关文章

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

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

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

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

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

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

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

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

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

    既然有了可持久化数组,就有可持久化并查集.. 由于上课讲过说是只能按秩合并(但是我也不确定...),所以就先写了按秩合并,相当于是维护fa[]和rk[] getf就是在这棵树中找,直到找到一个点的fa ...

  6. bzoj 3674 可持久化并查集加强版——可持久化并查集

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3674 用主席树维护 fa[ ]  和 siz[ ] .改 fa[ ] 和改 siz[ ] 都 ...

  7. BZOJ 3674: 可持久化并查集加强版

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3674 题意:三种操作:(1)合并ab所在集合:(2)查询ab是否在一个集合:(3) ...

  8. BZOJ 3674 可持久化并查集加强版 可持久化并查集

    题目大意:同3673 强制在线 同3673 仅仅只是慢了一些0.0 这道题仅仅写路径压缩比仅仅写启示式合并要快一点点 两个都写就慢的要死0.0 改代码RE的可能是内存不够 #include<cs ...

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

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

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

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

随机推荐

  1. Shell记录-Shell命令(其他)

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. .命令格式 top [参数] Shell 2.命令功能 显示当前系统正在执行的 ...

  2. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries

    https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...

  3. 如何安装ioncube扩展对PHP代码加密

    禅道专业版本的核心代码都是加密的(前端的html, css, js, 配置,语言项是开源的)的,使用的加密软件是 ioncube,因此要能运行禅道专业版本的软件,先要按照ioncube扩展. 一.下载 ...

  4. JavaScript 时间与时间戳转换

    一.获取yyyy-MM-dd hh:mm:ss 格式的时间 function getdate(timeStamp) { if (timeStamp) { var now = new Date(time ...

  5. [hadoop]mapreduce原理简述

    1.用于map的输入,先将输入数据切分成相等的分片,为每一个分片创建一个map worker,这里的切片大小不是随意订的,一般是与HDFS块大小一致,默认是64MB,一个节点上存储输入数据切片的最大s ...

  6. LintCode 387: Smallest Difference

    LintCode 387: Smallest Difference 题目描述 给定两个整数数组(第一个是数组A,第二个是数组B),在数组A中取A[i],数组B中取B[j],A[i]和B[j]两者的差越 ...

  7. 手写简化版printf函数

    2019.02.01更新:经同学提醒,myprintf函数应有返回值为输出的字符数. 期末的大作业,手写一个myprintf函数,支持如下一些操作. 也就是  % -(负号控制左右对齐) 数(控制字段 ...

  8. 用threading和Queue模块实现多线程的端口扫描器

    一.Queue模块基础 q = Queue.Queue()    q.qsize()           返回队列的大小  q.empty()         如果队列为空,返回True,反之Fals ...

  9. GRUB (简体中文)

    原文链接:https://wiki.archlinux.org/index.php/GRUB_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) 前言 引导程序是计算机启动时 ...

  10. go 函数的作用域及可见性

    1.全局变量,在程序整个生命周期有效 比如: test.go 中 我们定义 了 a 作为全局变量,那么在这个程序中任何地方都可以调用a, 这个 2. 局部变量,分为两种:1)函数内定义,2)语句块内定 ...