题目
做法
((0))区间生长((1))区间换点((2))单点查询
考虑仅一次区间换点((l,r,x)),区间生长:
就相当于换点后的生长的点在l时接在(x)上,到(r+1)时再接回去
有多次换点也同理,对每个换点新增一个虚点,建立一条虚链,每次生长则(link)到最近的前一个虚点
然后离线升序排树处理
My complete code
#include<bits/stdc++.h>
using namespace std;
typedef int LL;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){ if(c=='-')c=-1; c=getchar(); }
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
const LL maxn=1e6;
LL n,m,nod,tot,now,num;
LL son[maxn][2],fa[maxn],size[maxn],w[maxn],r[maxn],ans[maxn],sta[maxn],pos[maxn],gl[maxn],gr[maxn];
inline bool Nroot(LL x){ return (son[fa[x]][0]==x || son[fa[x]][1]==x); }
inline void Update(LL x){ size[x]=size[son[x][0]]+size[son[x][1]]+w[x]; }
inline void Rotate(LL x){
LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
if(Nroot(y)) son[z][son[z][1]==y]=x; fa[x]=z;
son[y][lz]=son[x][lz^1];
if(son[y][lz]) fa[son[y][lz]]=y;
son[x][lz^1]=y, fa[y]=x;
Update(y), Update(x);
}
inline void Splay(LL x){
while(Nroot(x)){
LL y=fa[x];
if(Nroot(y)){
LL z(fa[y]);
((son[y][1]==x)^(son[z][1]==y))?Rotate(y):Rotate(x);
}Rotate(x);
}
}
inline LL Access(LL x){
LL lst(x);
for(LL y=0;x;y=x,x=fa[x])
lst=x, Splay(x), son[x][1]=y, Update(x);
return lst;
}
inline void Link(LL x,LL y){
Splay(x), fa[x]=y;
}
inline void Cut(LL x){
Access(x), Splay(x);
son[x][0]=fa[son[x][0]]=0;
Update(x);
}
inline LL Lca(LL x,LL y){
Access(x); return Access(y);
}
struct node{
LL tree,id,x,y;
}a[maxn];
inline bool cmp(node x,node y){
if(!(x.tree ^ y.tree)) return x.id<y.id;
return x.tree<y.tree;
}
int main(){
n=Read(), m=Read();
nod=w[1]=size[1]=pos[1]=gl[1]=1,gr[1]=n;
Link(now=tot=2,1);
for(LL i=1;i<=m;++i){
LL opt(Read()),l(Read()),r(Read());
if(opt==0){
Link(pos[++nod]=++tot,now);
w[tot]=size[tot]=1;
gl[nod]=l, gr[nod]=r;
}else if(opt==1){
LL x; cin>>x;
l=max(l,gl[x]), r=min(r,gr[x]);
if(l>r) continue;
Link(++tot,now);
a[++num]=(node){l,i-m,tot,pos[x]};
a[++num]=(node){r+1,i-m,tot,now};
now=tot;
}else{
LL x(l),u(r),v(Read());
a[++num]=(node){x,++ans[0],pos[u],pos[v]};
}
}
sort(a+1,a+1+num,cmp);
for(LL i=1;i<=num;++i){
if(a[i].id>0){
LL x(a[i].x),y(a[i].y),lca(Lca(x,y));
Access(x), Splay(x); ans[a[i].id]+=size[x];
Access(y), Splay(y); ans[a[i].id]+=size[y];
Access(lca), Splay(lca); ans[a[i].id]-=2*size[lca];
}else
Cut(a[i].x),Link(a[i].x,a[i].y);
}
for(LL i=1;i<=ans[0];++i) printf("%d
",ans[i]);
return 0;
}