按照oi wiki,我的代码第81行应该写成82行的样子,然而会TLE 72分;将fa与fb交换写成81行的样子才能AC。说明我的可持久化并查集需要将大的树挂到小的树上???
#include<stdio.h>
#include<algorithm>
#define MAXN 2000005
using namespace std;
class node{
public:
int l,r,w,d;
}t[MAXN*4];
int n,m,rt[MAXN],cnt,ta,tb,tk,op,now,fa,fb,da,db;
int build(int l,int r){
int k=++cnt;
if(l==r){
t[k].w=l;t[k].d=1;
return k;
}
int mid=(l+r)>>1;
t[k].l=build(l,mid);
t[k].r=build(mid+1,r);
return k;
}
int ch_fa(int k,int l,int r,int s,int y){
int nod=++cnt;
t[nod].l=t[k].l;t[nod].r=t[k].r;t[nod].w=t[k].w;t[nod].d=t[k].d;
if(l==r){
t[nod].w=y;
return nod;
}
int mid=(l+r)>>1;
if(s<=mid)t[nod].l=ch_fa(t[k].l,l,mid,s,y);
else t[nod].r=ch_fa(t[k].r,mid+1,r,s,y);
return nod;
}
void ch_dep(int k,int l,int r,int s,int y){
if(l==r){
t[k].d=max(t[k].d,y);
return ;
}
int mid=(l+r)>>1;
if(s<=mid)ch_dep(t[k].l,l,mid,s,y);
else ch_dep(t[k].r,mid+1,r,s,y);
return ;
}
int ask_fa(int k,int l,int r,int s){
if(l==r){
return t[k].w;
}
int mid=(l+r)>>1;
if(s<=mid)return ask_fa(t[k].l,l,mid,s);
else return ask_fa(t[k].r,mid+1,r,s);
}
int ask_dep(int k,int l,int r,int s){
if(l==r){
return t[k].d;
}
int mid=(l+r)>>1;
if(s<=mid)return ask_fa(t[k].l,l,mid,s);
else return ask_fa(t[k].r,mid+1,r,s);
}
int findd(int k,int s){
int f=ask_fa(k,1,n,s);
if(s==f)return f;
return findd(k,f);
}
int main(){
//freopen("P3402_1.in","r",stdin);
//freopen("P3402.out","w",stdout);
scanf("%d%d",&n,&m);
rt[0]=build(1,n);
for(int i=1;i<=m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d",&ta,&tb);
fa=findd(rt[i-1],ta);
fb=findd(rt[i-1],tb);
if(fa!=fb){
da=ask_dep(rt[i-1],1,n,fa);
db=ask_dep(rt[i-1],1,n,fb);
if(da>db){
swap(fa,fb);swap(da,db);
}//现在fa较小
rt[i]=ch_fa(rt[i-1],1,n,fb,fa);
//小的父亲是大的 rt[i]=ch_fa(rt[i-1],1,n,fa,fb)
ch_dep(rt[i],1,n,fa,db+1);
}
else rt[i]=rt[i-1];
}
else if(op==2){
scanf("%d",&tk);
rt[i]=rt[tk];
}
else if(op==3){
scanf("%d%d",&ta,&tb);
//printf("%d %d %d df\n",i-1,findd(rt[i-1],ta),findd(rt[i-1],tb));
if(findd(rt[i-1],ta)==findd(rt[i-1],tb)){
puts("1");
}
else puts("0");
rt[i]=rt[i-1];
}
}
return 0;
}