bzoj3674 可持久化并查集加强版

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

Sample Input

5 6

1 1 2

3 1 2

2 1

3 0 3

2 1

3 1 2

Sample Output

1

0

1

正解:可持久化线段树+启发式合并。

原来可持久化数组就是用可持久化线段树维护。。那么我们每次合并时,直接将秩小的合并到秩大的树上面,注意秩相等的时候秩要加1。询问的话就直接在线段树里找当前点的根,撤回的话直接把当前时间的根赋值成历史时间的根就行了。

其实我只AC了加强版,普通版怎么也AC不了。。有人帮我查一下错吗qwq。。

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf (1<<30)
14 #define N (200010)
15 #define il inline
16 #define RG register
17 #define ll long long
18
19 using namespace std;
20
21 int sum[80*N],dep[80*N],ls[80*N],rs[80*N],rt[N],n,m,sz,ans;
22
23 il int gi(){
24     RG int x=0,q=1; RG char ch=getchar(); while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();
25     if (ch==‘-‘) q=-1,ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return q*x;
26 }
27
28 il void build(RG int &x,RG int l,RG int r){
29     x=++sz; if (l==r){ sum[x]=l,dep[x]=1; return; }
30     RG int mid=(l+r)>>1; build(ls[x],l,mid),build(rs[x],mid+1,r); return;
31 }
32
33 il void add(RG int x,RG int &y,RG int l,RG int r,RG int u){ //dep+1
34     y=++sz; if (l==r){ sum[y]=u,dep[y]=dep[x]+1; return; }
35     ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1;
36     u<=mid ? add(ls[x],ls[y],l,mid,u) : add(rs[x],rs[y],mid+1,r,u); return;
37 }
38
39 il void merge(RG int x,RG int &y,RG int l,RG int r,RG int u,RG int fa){ //按秩合并
40     y=++sz; if (l==r){ sum[y]=fa,dep[y]=dep[x]; return; }
41     ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1;
42     u<=mid ? merge(ls[x],ls[y],l,mid,u,fa) : merge(rs[x],rs[y],mid+1,r,u,fa); return;
43 }
44
45 il int query(RG int x,RG int l,RG int r,RG int u){ //查询当前结点的编号
46     if (l==r) return x; RG int mid=(l+r)>>1;
47     return u<=mid ? query(ls[x],l,mid,u) : query(rs[x],mid+1,r,u);
48 }
49
50 il int find(RG int rt,RG int u){ RG int y=query(rt,1,n,u); return sum[y]==u ? y : find(rt,sum[y]); } //找根
51
52 il void work(){
53     n=gi(),m=gi(); RG int x,y,type; build(rt[0],1,n);
54     for (RG int i=1;i<=m;++i){
55     type=gi(),rt[i]=rt[i-1];
56     if (type==1){
57         x=gi()^ans,y=gi()^ans;
58         x=find(rt[i],x),y=find(rt[i],y);
59         if (dep[x]>dep[y]) swap(x,y);
60         merge(rt[i-1],rt[i],1,n,sum[x],sum[y]);
61         if (dep[x]==dep[y]) add(rt[i],rt[i],1,n,sum[y]);
62     } else if (type==2) x=gi()^ans,rt[i]=rt[x]; else{
63         x=gi()^ans,y=gi()^ans;
64         ans=sum[find(rt[i],x)]==sum[find(rt[i],y)];
65         printf("%d\n",ans);
66     }
67     }
68     return;
69 }
70
71 int main(){
72     work();
73     return 0;
74 }
时间: 2024-08-26 04:37:45

bzoj3674 可持久化并查集加强版的相关文章

bzoj3673可持久化并查集 by zky&amp;&amp;bzoj3674可持久化并查集加强版

bzoj3673可持久化并查集 by zky 题意: 维护可以恢复到第k次操作后的并查集. 题解: 用可持久化线段树维护并查集的fa数组和秩(在并查集里的深度),不能路径压缩所以用按秩启发式合并,可以使合并均摊复杂度为O(nlog2n).可持久化线段树实际上就是在更新节点时按主席树的插入方式新建一条路径(其实主席树就是可持久化权值线段树). 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm&g

[BZOJ3674]可持久化并查集加强版&amp;[BZOJ3673]可持久化并查集 by zky

思路: 用主席树维护并查集森林,每次连接时新增结点. 似乎并不需要启发式合并,我随随便便写了一个就跑到了3674第一页?3673是这题的弱化版,本来写个暴力就能过,现在借用加强版的代码(去掉异或),直接吊打暴力程序. 1 #include<cstdio> 2 #include<cctype> 3 inline int getint() { 4 register char ch; 5 while(!isdigit(ch=getchar())); 6 register int x=ch

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

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 3674: 可持久化并查集加强版 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 3225  Solved: 1192[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后--hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可

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

3674: 可持久化并查集加强版 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 2605  Solved: 977[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状

【BZOJ3674】可持久化并查集加强版

可持久化并查集我觉得就是可持久化数组的一种应用.可持久化数组,顾名思义,就是有历史版本的数组,那么如果我们暴力修改储存的话,修改O(n)查询O(1),空间O(n*m),这样肯定不可行,那么我们发现主席树有这样的功能,他可以快速复制,修改O(log),查询O(log),空间(m*log),是一个可行的方案.然后我们可持久化f数组维护fa,每次按照深度启发式合并,不进行路径压缩,这样能保证时间复杂度位单次O(log^2),空间复杂度为O(2*n+m*log).我不知道为什么不路径压缩,路径压缩是完全

bzoj3674: 可持久化并查集

用可持久化线段树维护可持久化并查集. 调了一下午,改为按秩合并就过了... #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=200100; const int INF=1e9+10; int n,m; int fa[ma

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

Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 3592  Solved: 1337[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询

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

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 2515  Solved: 1107 [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 Inp

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

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 http://www.lydsy.com/JudgeOnline/problem.php?id=3673 双倍经验啦啦啦.. 给主席树换了个名称果然高大上... 首先要可持久化并查集其实就是可持久化数组... 那么因为数组的形式是这样的$P[x]$,那么我们用一种数据结构实现查找x返回对应的$P[x]$即可啦啦啦. 然后那么我所学的可持久化目前只有主席树QAQ哪天去写写fhqtreap...