题解爸爸戳这里
splay维护括号序实在不敢尝试
建虚点LCT 还是很资瓷的哇 正如dls所说的 小清新数据结构
注意的是求两点距离 不能直接拉出那条链 而是要求LCA
然后我发现我不会求LCA了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=400005;
struct node{
node *ch[2],*f;
int v,s; bool rev;
bool isr() { return !f || (f->ch[0]!=this && f->ch[1]!=this); }
bool dir() { return f->ch[1]==this; }
void setc(node *x,int d) { ch[d]=x; if (x) x->f=this; }
void push(){
if (rev) { swap(ch[0],ch[1]); if(ch[0])ch[0]->rev^=1; if(ch[1])ch[1]->rev^=1; rev=0; }
}
void upd(){
s=v; if(ch[0]) s+=ch[0]->s; if (ch[1]) s+=ch[1]->s;
}
}pool[N];
inline void rot(node *x){
bool d=x->dir(); node *p=x->f;
if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->upd();
}
stack<node*> sta;
inline void splay(node *x){
node *q=x; while (!q->isr()) sta.push(q),q=q->f; sta.push(q);
while (!sta.empty()) sta.top()->push(),sta.pop();
while (!x->isr())
if (x->f->isr()) rot(x);
else if (x->dir()==x->f->dir()) rot(x->f),rot(x);
else rot(x),rot(x);
x->upd();
}
inline node *expose(node *x){
node *p;
for (node *q=NULL;x;q=x,x=x->f)
p=x,splay(x),x->ch[1]=q,x->upd();
return p;
}
inline void link(node *x,node *y) { x->f=y; expose(x); }
inline void cut(node *x){ expose(x); splay(x); x->ch[0]->f=NULL; x->ch[0]=NULL; x->upd(); }
inline int query(node *x){ expose(x); splay(x); return x->s; }
int n,m;
struct event{
int f,t,x,y,z;
event(int f=0,int t=0,int x=0,int y=0,int z=0):f(f),t(t),x(x),y(y),z(z) { }
bool operator < (const event &B) const{
return t==B.t?f<B.f:t<B.t;
}
}eve[N]; int tot;
int ans[N],idx;
int fat[N],cur;
const int B=2e5;
int lp[N],rp[N];
int main(){
int order,cur,l,r,x,y,z; node *lca;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
cur=1; int cnt=1; lp[1]=1; rp[1]=n;
pool[1].v=pool[1].s=1;
link(pool+B+cur,pool+1);
for (int i=1;i<=m;i++){
read(order);
if (order==0){
read(l); read(r);
++cnt; pool[cnt].s=pool[cnt].v=1;
lp[cnt]=l; rp[cnt]=r;
link(pool+cnt,pool+B+cur);
}else if (order==1){
read(l); read(r); read(x);
l=max(l,lp[x]); r=min(r,rp[x]);
if (l<=r){
++cur;
link(pool+B+cur,pool+B+cur-1);
eve[++tot]=event(1,l,cur,x);
eve[++tot]=event(0,r+1,cur,x);
}
}else{
read(x); read(l); read(r);
eve[++tot]=event(2,x,l,r,++idx);
}
}
sort(eve+1,eve+tot+1);
for (int i=1;i<=tot;i++)
if (eve[i].f==1){
x=eve[i].x; y=eve[i].y;
cut(pool+B+x);
link(pool+B+x,pool+y);
}else if (eve[i].f==0){
x=eve[i].x; y=eve[i].y;
cut(pool+B+x);
link(pool+B+x,pool+B+x-1);
}else{
x=eve[i].x; y=eve[i].y; z=eve[i].z;
expose(pool+x); splay(pool+x); ans[z]+=pool[x].s;
lca=expose(pool+y); splay(pool+y); ans[z]+=pool[y].s;
expose(lca); splay(lca); ans[z]-=(lca->s)<<1;
}
for (int i=1;i<=idx;i++)
printf("%d\n",ans[i]);
return 0;
}