两个都是可持久化线段树,相当于复习一下算法。。
第一个程序我没加路径压缩,第二个加了
第二个读入的操作编号不要异或lastans……在这里卡了一下
#include<cstdio>
#include<algorithm>
using namespace std;
struct SegTree{
int l,r,ls,rs,v;
}tree[2000005];
int root[20005],cnt,deep[200005],n,m;
void Build(int &rt,int l,int r){
if(!rt)rt=++cnt;
if(l==r){tree[rt].v=l;return;}
int mid=l+r>>1;
tree[rt].l=l;
tree[rt].r=r;
Build(tree[rt].ls,l,mid);
Build(tree[rt].rs,mid+1,r);
}
void Change(int x,int &y,int pos,int val){
y=++cnt;
tree[y].l=tree[x].l;
tree[y].r=tree[x].r;
if(tree[x].l==tree[x].r){tree[y].v=val;deep[y]=deep[x];return;}
tree[y].ls=tree[x].ls;
tree[y].rs=tree[x].rs;
int mid=tree[x].l+tree[x].r>>1;
if(pos<=mid)Change(tree[x].ls,tree[y].ls,pos,val);
if(pos>mid)Change(tree[x].rs,tree[y].rs,pos,val);
}
int Query(int rt,int pos){
if(tree[rt].l==tree[rt].r)return rt;
int mid=tree[rt].l+tree[rt].r>>1;
if(pos<=mid)return Query(tree[rt].ls,pos);
if(pos>mid)return Query(tree[rt].rs,pos);
}
void Add(int rt,int pos){
if(tree[rt].l==tree[rt].r){deep[rt]++;return;}
int mid=tree[rt].l+tree[rt].r>>1;
if(pos<=mid)Add(tree[rt].ls,pos);
if(pos>mid)Add(tree[rt].rs,pos);
}
int Find(int rt,int x){
int tp=Query(rt,x);
if(x==tree[tp].v)return tp;
return Find(rt,tree[tp].v);
}
int main(){
freopen("3673.in","r",stdin);
freopen("3673.out","w",stdout);
scanf("%d %d",&n,&m);
Build(root[0],1,n);
for(int i=1;i<=m;i++){
int opt;
scanf("%d",&opt);
if(opt==1){
int x,y,px,py;
scanf("%d %d",&x,&y);
root[i]=root[i-1];
px=Find(root[i],x);py=Find(root[i],y);
if(tree[px].v==tree[py].v)continue;
if(deep[px]>deep[py])swap(px,py);
Change(root[i-1],root[i],tree[px].v,tree[py].v);
if(deep[px]==deep[py])Add(root[i],tree[py].v);
}
if(opt==2){
int k;
scanf("%d",&k);
root[i]=root[k];
}
if(opt==3){
int x,y;
root[i]=root[i-1];
scanf("%d %d",&x,&y);
if(tree[Find(root[i],x)].v!=tree[Find(root[i],y)].v)puts("0");
else puts("1");
}
}
return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,cnt,lastans=0,deep[10000005],root[200005];
struct SegTree{
int l,r,ls,rs,v;
}tree[10000005];
void Build(int &rt,int l,int r){
if(!rt)rt=++cnt;
tree[rt].l=l;
tree[rt].r=r;
if(l==r){tree[rt].v=l;return;}
int mid=l+r>>1;
Build(tree[rt].ls,l,mid);
Build(tree[rt].rs,mid+1,r);
}
void Change(int x,int &y,int pos,int val){
y=++cnt;
tree[y].l=tree[x].l;
tree[y].r=tree[x].r;
if(tree[x].l==tree[x].r){tree[y].v=val;deep[y]=deep[x];return;}
tree[y].ls=tree[x].ls;
tree[y].rs=tree[x].rs;
int mid=tree[x].l+tree[x].r>>1;
if(pos<=mid)Change(tree[x].ls,tree[y].ls,pos,val);
if(pos>mid)Change(tree[x].rs,tree[y].rs,pos,val);
}
void Add(int rt,int pos){
if(tree[rt].l==tree[rt].r){deep[rt]++;return;}
int mid=tree[rt].l+tree[rt].r>>1;
if(pos<=mid)Add(tree[rt].ls,pos);
if(pos>mid)Add(tree[rt].rs,pos);
}
int Query(int rt,int pos){
if(tree[rt].l==tree[rt].r){return rt;}
int mid=tree[rt].l+tree[rt].r>>1;
if(pos<=mid)return Query(tree[rt].ls,pos);
if(pos>mid)return Query(tree[rt].rs,pos);
}
int Find(int rt,int x){
int p=Query(rt,x);
if(x==tree[p].v){return p;}
int tp=Find(rt,tree[p].v);
Change(rt,rt,tree[p].v,tp);
return tp;
}
int main(){
freopen("3674.in","r",stdin);
freopen("3674.out","w",stdout);
scanf("%d %d",&n,&m);
Build(root[0],1,n);
for(int i=1;i<=m;i++){
int opt;
scanf("%d",&opt);
if(opt==1){
int x,y,p,q;
scanf("%d %d",&x,&y);
x^=lastans;y^=lastans;
root[i]=root[i-1];
p=Find(root[i],x);
q=Find(root[i],y);
if(tree[p].v==tree[q].v)continue;
if(deep[p]>deep[q])swap(p,q);
Change(root[i-1],root[i],tree[p].v,tree[q].v);
if(deep[p]==deep[q])Add(root[i],tree[q].v);
}
if(opt==2){
int k;
scanf("%d",&k);
k^=lastans;
root[i]=root[k];
}
if(opt==3){
int x,y;
scanf("%d %d",&x,&y);
x^=lastans;y^=lastans;
root[i]=root[i-1];
if(tree[Find(root[i],x)].v==tree[Find(root[i],y)].v){puts("1");lastans=1;}
else {puts("0");lastans=0;}
}
}
return 0;
}