传送门
一点也没加强好不好
主席树+并查集启发式合并,实现nlog^2n的复杂度。
速度快到飞起。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 10000005
using namespace std;
int ls[N],rs[N],id[N],dep[N],rt[N/40];
int n,m,fl,x,y,sz,ans;
void build(int &x,int l,int r){
x=++sz;
if (l==r){
id[x]=l;
return;
}
int mid=(l+r)/2;
build(ls[x],l,mid);
build(rs[x],mid+1,r);
}
void change(int &nx,int x,int l,int r,int p,int q){
nx=++sz;
if (l==r){
id[nx]=q;
dep[nx]=dep[x];
return;
}
ls[nx]=ls[x],rs[nx]=rs[x];
int mid=(l+r)/2;
if (p<=mid) change(ls[nx],ls[x],l,mid,p,q);
else change(rs[nx],rs[x],mid+1,r,p,q);
}
int ask(int x,int l,int r,int p){
if (l==r) return x;
int mid=(l+r)/2;
if (p<=mid) return ask(ls[x],l,mid,p);
return ask(rs[x],mid+1,r,p);
}
void add(int x,int l,int r,int p){
if (l==r) {dep[x]++; return;}
int mid=(l+r)/2;
if (p<=mid) add(ls[x],l,mid,p);
else add(rs[x],mid+1,r,p);
}
int find(int x,int y){
int t=ask(x,1,n,y);
while (id[t]!=y){
y=id[t];
t=ask(x,1,n,y);
}
return t;
}
int main(){
scanf("%d%d",&n,&m);
build(rt[0],1,n);
for (int i=1;i<=m;i++){
scanf("%d",&fl);
if (fl==1){
rt[i]=rt[i-1];
scanf("%d%d",&x,&y);
x^=ans; y^=ans;
x=find(rt[i],x);
y=find(rt[i],y);
if (id[x]!=id[y]){
if (dep[x]>dep[y]) swap(x,y);
change(rt[i],rt[i-1],1,n,id[x],id[y]);
if (dep[x]==dep[y]) add(rt[i],1,n,id[y]);
}
}
if (fl==2){
scanf("%d",&x);
rt[i]=rt[x^ans];
}
if (fl==3){
rt[i]=rt[i-1];
scanf("%d%d",&x,&y);
x^=ans; y^=ans;
x=find(rt[i],x);
y=find(rt[i],y);
ans=(x==y)?1:0;
printf("%d\n",ans);
}
}
}
或者直接使用stl中的rope,跑得也不慢。
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
rope <int> *rp[200010];
int n,m,a[200100],f,x,y,lastans;
int get(int i,int x){
int fa=rp[i]->at(x);
if (fa==x) return x;
int f=get(i,fa);
if (f==fa) return f;
rp[i]->replace(x,f);
return f;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) a[i]=i;
rp[0]=new rope<int> (a,a+n+1);
for (int i=1;i<=m;i++){
rp[i]=new rope<int> (*rp[i-1]);
scanf("%d",&f);
if (f==1){
scanf("%d%d",&x,&y);
x^=lastans;
y^=lastans;
x=get(i,x);
y=get(i,y);
if (x!=y) rp[i]->replace(y,x);
}
else if (f==2){
scanf("%d",&x);
x^=lastans;
rp[i]=rp[x];
}
else if (f==3){
scanf("%d%d",&x,&y);
x^=lastans;
y^=lastans;
printf("%d\n",lastans=(get(i,x)==get(i,y)));
}
}
}