小 Y 家里有一个大森林,里面有 n n n 棵树,编号从 1 1 1 到 n n n。一开始这些树都只是树苗,只有一个节点,标号为 1 1 1。这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力。小 Y 掌握了一种魔法,能让第 l l l 棵树到第 r r r 棵树的生长节点长出一个子节点。同时她还能修改第 l l l 棵树到第 r r r 棵树的生长节点。她告诉了你她使用魔法的记录,你能不能管理她家的森林,并且回答她的询问呢?
第一行包含两个正整数 n , m n,m n,m,表示共有 n n n 棵树和 m m m 个操作。
接下来 m m m 行,每行包含若干非负整数表示一个操作,操作格式为:
0 l r
表示将第 l l l 棵树到第 r r r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 0 0 号操作叶子标号加 1 1 1(例如,第一个 0 0 0 号操作产生的子节点标号为 2 2 2), l l l 到 r r r 之间的树长出的节点标号都相同。保证 1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1≤l≤r≤n 。
1 l r x
表示将第 l l l 棵树到第 r r r 棵树的生长节点改到标号为 x x x 的节点。对于 i i i ( l ≤ i ≤ r ) (l \leq i \leq r) (l≤i≤r) 这棵树,如果标号 x x x 的点不在其中,那么这个操作对该树不产生影响。保证 1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1≤l≤r≤n , x x x 不超过当前所有树中节点最大的标号。
2 x u v
询问第 x x x 棵树中节点 u u u 到节点 v v v 点的距离,也就是在第 x x x 棵树中从节点 u u u 和节点 v v v 的最短路上边的数量。保证 1 ≤ x ≤ n 1 \leq x \leq n 1≤x≤n,这棵树中节点 u u u 和节点 v v v 存在。
输出包括若干行,按顺序对于每个小 Y 的询问输出答案
5 5
0 1 5
1 2 4 2
0 1 4
2 1 1 3
2 2 1 3
1
2
N ≤ 1 0 5 , M ≤ 2 × 1 0 5 N \leq 10^5, \ M \leq 2 \times 10^5 N≤105, M≤2×105
0号操作只会对1号操作的范围造成影响,除此之外可以看作所有树都加了某一个点。
先假设所有操作都是针对所有树的。对每一个1号操作建立新的虚点,虚点连向操作改的那个点。生长的时候新的叶子连向上一次的虚点。
在操作只针对部分树的时候,先把所有虚点连向上一个虚点。将修改拆成左端点和右端点加一。将修改和询问按照树的编号排序。当进行到左端点的时候,将虚点的父亲连向实点;右端点把虚点的父亲连向上一个虚点。
讲的不清楚,直接看代码吧。。。
另:请注意,最后答案为:路径实点的数量-[LCA是虚点],可能要注意一下。
#include
#include
#include
#include
#include
#include
using namespace std;
const int Q=433333;
int si[Q],fa[Q],ls[Q],rs[Q],ct[Q];
void upd(int x)
{
si[x]=si[ls[x]]+si[rs[x]]+ct[x];
}
bool isroot(int x)
{return ls[fa[x]]!=x&&rs[fa[x]]!=x;}
void xxx(int x)
{
int y=fa[x],z=fa[y];
if(ls[z]==y)ls[z]=x;
if(rs[z]==y)rs[z]=x;
if(ls[y]==x)ls[y]=rs[x],fa[ls[y]]=y,rs[x]=y;
else rs[y]=ls[x],fa[rs[y]]=y,ls[x]=y;
fa[x]=z,fa[y]=x;
upd(y),upd(x);
}
void splay(int x)
{
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
if((ls[z]==y&&ls[y]==x)||(rs[z]==y&&rs[y]==x))
xxx(y),xxx(x);
else xxx(x),xxx(x);
else xxx(x);
}
}
int AC(int x)
{
int t=0;
while(x)
{
splay(x);
rs[x]=t;
upd(x);
t=x;
x=fa[x];
}
return t;
}
void link(int x,int y)
{
splay(x);
fa[x]=y;
}
void cut(int x)
{
AC(x);
splay(x);
fa[ls[x]]=0;
ls[x]=0;
upd(x);
}
int maxq=0;
struct qu{
int tr,p,x,y;
}q[Q];
bool operator<(qu a,qu b)
{
return a.tr==b.tr?a.py)continue;
ct[++tot]=0;
si[tot]=0;
link(tot,lasroot);
q[++maxq]=(qu){x,i-m,tot,tre[v]};
q[++maxq]=(qu){y+1,i-m,tot,lasroot};
lasroot=tot;
}
else{
scanf("%d%d%d",&v,&x,&y);
q[++maxq]=(qu){v,i,tre[x],tre[y]},pt[i]=++OB;
}
}
sort(q+1,q+maxq+1);
for(int i=1;i<=maxq;i++)
{
x=q[i].x,y=q[i].y;
if(q[i].p>0)
{
id=pt[q[i].p];
AC(x);splay(x);
ans[id]+=si[x];
int t=AC(y);splay(y);
ans[id]+=si[y];
AC(t),splay(t);
ans[id]-=(si[t]<<1);
}
else{
cut(x);
link(x,y);
}
}
for(int i=1;i<=OB;i++)
printf("%d\n",ans[i]);
return 0;
}