【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
最后还是去掉异或顺手A了3673,,,
并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦
1:判断是否属于同一集合,我加了路径压缩。
2:直接把跟的值指向root[k]的值破之。
3:输出判断即可。
难者不会,会者不难,1h前我还在膜这道题,现在吗hhh就当支持下zky学长出的题了。
3673:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() #define for1(i,a,n) for(int i=(a);i<=(n);++i) using namespace std; inline const int getint(){ char c= getchar (); int k=1,r=0; for (;c< '0' ||c> '9' ;c= getchar ()) if (c== '-' )k=-1; for (;c>= '0' &&c<= '9' ;c= getchar ())r=r*10+c- '0' ; return k*r;} const int N=2*1E4+10; struct node{ int l,r,f;}T[N*100]; int cnt,root[N],n,m; inline void update( int l, int r, int &pos, int x, int fa){ T[++cnt]=T[pos]; pos=cnt; if (l==r) {T[pos].f=fa; return ;} int mid=(l+r)>>1; if (x<=mid) update(l,mid,T[pos].l,x,fa); else update(mid+1,r,T[pos].r,x,fa); } inline int ask( int l, int r, int pos, int x){ if (l==r) return T[pos].f; int mid=(l+r)>>1; if (x<=mid) return ask(l,mid,T[pos].l,x); else return ask(mid+1,r,T[pos].r,x); } inline int un( int &rt, int a, int b){ update(1,n,rt,a,b); return b; } inline int find( int &rt, int y){ int f=ask(1,n,rt,y); return f==y?y:un(rt,y,find(rt,f)); } int main(){ read(n); read(m); int fx,fy,x,y,c; for1(i,1,n) update(1,n,root[0],i,i); for1(i,1,m){ read(c); root[i]=root[i-1]; switch (c){ case 1: read(x); read(y); fx=find(root[i],x),fy=find(root[i],y); if (fx!=fy) un(root[i],fx,fy); break ; case 2: root[i]=root[getint()]; break ; case 3: read(x); read(y); fx=find(root[i],x),fy=find(root[i],y); printf ( "%d\n" ,(fx==fy)); break ; } } return 0; } |
3674:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() #define for1(i,a,n) for(int i=(a);i<=(n);++i) using namespace std; inline const int getint(){ char c= getchar (); int k=1,r=0; for (;c< '0' ||c> '9' ;c= getchar ()) if (c== '-' )k=-1; for (;c>= '0' &&c<= '9' ;c= getchar ())r=r*10+c- '0' ; return k*r;} const int N=2*1E5+10; struct node{ int l,r,f;}T[N*100]; int cnt,root[N],n,m; inline void update( int l, int r, int &pos, int x, int fa){ T[++cnt]=T[pos]; pos=cnt; if (l==r) {T[pos].f=fa; return ;} int mid=(l+r)>>1; if (x<=mid) update(l,mid,T[pos].l,x,fa); else update(mid+1,r,T[pos].r,x,fa); } inline int ask( int l, int r, int pos, int x){ if (l==r) return T[pos].f; int mid=(l+r)>>1; if (x<=mid) return ask(l,mid,T[pos].l,x); else return ask(mid+1,r,T[pos].r,x); } inline int un( int &rt, int a, int b){ update(1,n,rt,a,b); return b; } inline int find( int &rt, int y){ int f=ask(1,n,rt,y); return f==y?y:un(rt,y,find(rt,f)); } int main(){ read(n); read(m); int fx,fy,last=0,x,y,c; for1(i,1,n) update(1,n,root[0],i,i); for1(i,1,m){ read(c); root[i]=root[i-1]; switch (c){ case 1: read(x); read(y); x^=last; y^=last; fx=find(root[i],x),fy=find(root[i],y); if (fx!=fy) un(root[i],fx,fy); break ; case 2: root[i]=root[getint()^last]; break ; case 3: read(x); read(y); x^=last; y^=last; fx=find(root[i],x),fy=find(root[i],y); printf ( "%d\n" ,last=(fx==fy)); break ; } } return 0; } |
这样就完了,然而只是达神几年前就随手虐的东西,本蒟蒻必须得努力啊!!!
NOI 2017 Bless All
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何统计不同电话号码的个数?—位图法
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 从零实现富文本编辑器#3-基于Delta的线性数据结构模型
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 管理100个小程序-很难吗
· 基于Blazor实现的运输信息管理系统
· 如何统计不同电话号码的个数?—位图法
· 微信支付功能的设计实现与关键实践(UniApp+Java)全代码