这题题解看lych_cys即可,我就不赘述了。
对于lych_cys的代码,我有个细心但效果显著的优化,那就是求两点间距离时,acss(a[k].x); splay(a[k].x); ans[a[k].op]=sum[a[k].x];
x=acss(a[k].y); splay(a[k].y); ans[a[k].op]+=sum[a[k].y];
acss(x); splay(x); ans[a[k].op]-=sum[x]<<1;
可改成
inline int dis(register int u,register int v){
register int ans=a[access(u)].s,x=access(v);
ans+=a[x].s;
ans-=a[access(x)].s<<1;
return ans;
}
因为在梁大的代码中, access(x)
的返回值 就是x所在重链的根,不必重新splay(x)
,再加上IO优化,uoj上就rk1了
#include
#include
#include
const int N=500005;
struct LCT{
struct node{
int l,r,fa,s,v;
}a[N];
inline bool isroot(int x){
return a[a[x].fa].l!=x && a[a[x].fa].r!=x;
}
inline void maintain(int x){
a[x].s=a[a[x].l].s+a[a[x].r].s+a[x].v;
}
inline void rotate(register int x){
register int y=a[x].fa,z=a[y].fa;
if(!isroot(y)){
if(a[z].l==y)a[z].l=x;
else a[z].r=x;
}
a[x].fa=z;
a[y].fa=x;
if(x==a[y].l){
a[y].l=a[x].r;
a[a[x].r].fa=y;
a[x].r=y;
}else{
a[y].r=a[x].l;
a[a[x].l].fa=y;
a[x].l=y;
}
maintain(y);
}
inline void splay(register int x){
register int u,v;
while(!isroot(x)){
u=a[x].fa,v=a[u].fa;
if(!isroot(u)){
if((a[v].l==u)^(a[u].l==x))rotate(x);
else rotate(u);
}
rotate(x);
}
maintain(x);
}
inline int access(register int x){
register int y=0;
for(;x;y=x,x=a[x].fa){
splay(x);
a[x].r=y;
maintain(x);
}
return y;
}
inline void cut(int x){
access(x),splay(x),a[a[x].l].fa=0,a[x].l=0,maintain(x);
}
inline void link(int x,int y){
splay(x);
a[x].fa=y;
}
inline int dis(register int u,register int v){
register int ans=a[access(u)].s,x=access(v);
ans+=a[x].s;
ans-=a[access(x)].s<<1;
return ans;
}
}t;
struct eve{
int id,o,x,y;
}a[N];
int m,n,xb,cnt,b[N],l[N],r[N],i,ans[N],o,x,y,u,v,now,tot,z;
bool cmp(eve a,eve b){
return a.idchar obuf[1500000],*oh=obuf,ibuf[7000000],*ih=ibuf;
inline void read(int&x){
x=0;
register char c;
while(!isdigit(c=*ih++));
for(;isdigit(c);c=*ih++)x=((x+(x<<2))<<1)+(c^48);
}
inline void print(register int x){
static int buf[30];
register int xb=0;
if(!x)*oh++='0';
else{
for(;x;x/=10)buf[++xb]=x%10;
while(xb)*oh++=buf[xb--]^48;
}
}
int main(){
//freopen("ex_forest2.in","r",stdin);
//freopen("2.txt","w",stdout);
fread(ibuf,1,7000000,stdin);
read(n);
read(m);
cnt=b[1]=1,now=xb=2;
t.a[1].v=1;
l[1]=1,r[1]=n;
t.link(2,1);
for(i=1;i<=m;++i){
ans[i]=-1;
read(o);
read(x);
read(y);
if(o==0){
t.link(b[++cnt]=++xb,now);
t.a[xb].v=1;
l[cnt]=x,r[cnt]=y;
}else read(z);
if(o==1){
if(l[z]>x)x=l[z];
if(r[z]if(x<=y){
++xb;
if(x>1)t.link(xb,now);
a[++tot]=(eve){x,-1,xb,b[z]};
a[++tot]=(eve){y+1,-1,xb,now};
now=xb;
}
}
if(o==2)a[++tot]=(eve){x,i,b[y],b[z]};
}
std::sort(a+1,a+tot+1,cmp);
for(i=1;i<=tot;++i)
if(~a[i].o)ans[a[i].o]=t.dis(a[i].x,a[i].y);
else t.cut(a[i].x),t.link(a[i].x,a[i].y);
for(i=1;i<=m;++i)if(~ans[i])print(ans[i]),*oh++='\n';
fwrite(obuf,1,oh-obuf,stdout);
return 0;
}