两个都是可持久化线段树,相当于复习一下算法。。
第一个程序我没加路径压缩,第二个加了
第二个读入的操作编号不要异或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; }