http://blog.csdn.net/lych_cys/article/details/53515748#
神想法啊…
至于求两点间距离为什么不能直接把两点的链拉出来
可以考虑因为树上虚点,两个点的LCA可以是一个虚点,虚点的父节点才是它们真正的LCA,所以直接拉一条链会导致少算一个点,而算LCA的话不会有这个问题(可以脑补一下)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#define N 100010
using namespace std;
int n,m,cnt,top,tot,g,cnt0;
int Ans[N],stc[N],L[N],R[N];
struct lef{
int Size,rev,key;
lef *ch[2],*fa;
int isr(){ return (!fa)||(fa->ch[0]!=this&&fa->ch[1]!=this); }
int isl(){ return fa&&fa->ch[1]==this; }
void Up(){ Size=key+(ch[0]?ch[0]->Size:0)+(ch[1]?ch[1]->Size:0); }
void reverse(){ access(); splay(); rev^=1; }
void Push(){
if(!rev) return ;
swap(ch[0],ch[1]);
if(ch[0]) ch[0]->rev^=1;
if(ch[1]) ch[1]->rev^=1;
rev=0;
}
lef *access(){
lef *t,*x,*p;
for(t=0,x=this;x;x=x->fa)
p=x,x->splay(),x->ch[1]=t,t=x,x->Up();
return p;
}
void splay(){
Pushtop();
for(lef *x=this;!x->isr();x->rot())
if(!x->fa->isr()) ((x->isl())^(x->fa->isl()))?x->rot():x->fa->rot();
}
void rot(){
lef *x=this,*y=x->fa,*z=y->fa; int wh=x->isl();
if(!y->isr()) z->ch[z->ch[1]==y]=x; x->fa=z;
if(y->ch[wh]=x->ch[wh^1]) y->ch[wh]->fa=y;
x->ch[wh^1]=y; y->fa=x;
y->Up(); x->Up();
}
void Pushtop(){ if(!isr()) this->fa->Pushtop(); Push(); }
}A[N<<2];
struct stp{int op,x,y,z,g;};
vector<stp> work[N];
inline void link(int x,int y){ A[x].reverse(); A[x].fa=&A[y]; A[x].access(); }
inline void cut(int x,int y){ A[x].reverse(); A[y].access(); A[y].splay(); A[y].ch[0]=A[x].fa=0; A[y].Up(); }
inline int query(int x,int y){
int ret=0; lef *lca; A[1].reverse();
A[x].access(); A[x].splay(); ret=A[x].Size;
lca=A[y].access(); A[y].splay(); ret+=A[y].Size;
lca->access(); lca->splay(); ret-=2*(lca->Size);
return ret;
}
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p2==p1)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline lef *newd(int x,int y){
A[x].Size=y; A[x].ch[0]=A[x].ch[1]=A[x].fa=0; A[x].key=y;
return &A[x];
}
int main(){
rea(n); rea(m);
newd(cnt=1,1); L[cnt]=1; R[cnt]=n;
newd(tot=m+1,0); link(tot,cnt);
for(int i=1;i<=m;i++){
int op; rea(op);
if(op==0){
++cnt; rea(L[cnt]); rea(R[cnt]);
newd(cnt,1); link(cnt,tot);
}
else if(op==1){
int l,r,x;
rea(l); rea(r); rea(x);
l=max(l,L[x]); r=min(r,R[x]);
if(l<=r){
newd(++tot,0); link(tot,tot-1);
work[l].push_back((stp){1,tot,tot-1,x});
work[r+1].push_back((stp){1,tot,x,tot-1});
}
}
else{
int x,y,z; rea(x); rea(y); rea(z);
work[x].push_back((stp){2,x,y,z,++cnt0});
}
}
for(int i=1;i<=n;i++){
stp now;
for(int j=0;j<work[i].size();j++){
now=work[i][j];
if(now.op==1){
cut(now.x,now.y); link(now.x,now.z);
}
else
Ans[now.g]=query(now.y,now.z);
}
}
for(int i=1;i<=cnt0;i++) printf("%d\n",Ans[i]);
return 0;
}