定义:
siz[]数组,用来保存以x为根的子树节点个数
top[]数组,用来保存当前节点的所在链的顶端节点
hson[]数组,用来保存重儿子
drep[]数组,用来保存当前节点的深度
fa[]数组,用来保存当前节点的父亲
id[]数组,用来保存树中每个节点剖分后的新编号
两遍dfs求出以上信息,连边成重链,按照新的编号建树(有的题目这一步可省略);剩下全是线段树的操作
查询或修改的话,因为在第二个dfs中优先构造重链,所以修改深度更深的x到top[x],x再换为fa[x],直到两点top相等;
一般链剖100多行,我强力缩行到87行。。。。。。。。
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define rs ((o<<1)|1)
#define ls (o<<1)
#define MAXX 300010
using namespace std;
struct data{
int nxt,to;
}edge[MAXX*2];
int segtree[MAXX*4],head[MAXX],top[MAXX],siz[MAXX],hson[MAXX],id[MAXX];
int n,f,t,m,deep[MAXX],fa[MAXX],lazy[MAXX*4],tot,sm,a,b;
void add(int fro,int too){edge[++tot].nxt=head[fro];edge[tot].to=too;head[fro]=tot;}
void dfs1(int num,int father){
hson[num]=0;deep[num]=deep[father]+1;siz[num]=1;fa[num]=father;
for(int i=head[num];i;i=edge[i].nxt)if(father!=edge[i].to){
int too=edge[i].to;
dfs1(too,num);
siz[num]+=siz[too];
if(siz[hson[num]]<siz[too])hson[num]=too;
}
}
void dfs2(int num,int toop){
id[num]=++sm;top[num]=toop;
if(hson[num])dfs2(hson[num],toop);
for(int i=head[num];i;i=edge[i].nxt)if(edge[i].to!=hson[num]&&edge[i].to!=fa[num])dfs2(edge[i].to,edge[i].to);
}
void down(int o,int l,int r){
int mid=(r+l)>>1;
segtree[ls]+=(mid-l+1)*lazy[o],segtree[rs]+=lazy[o]*(r-mid);
lazy[rs]+=lazy[o],lazy[ls]+=lazy[o],lazy[o]=0;
}
void update(int o,int L,int R,int ll,int rr){
if(L!=R)down(o,L,R);
if(L>=ll&&R<=rr){segtree[o]+=(R-L+1);lazy[o]++;return;}
int mid=(L+R)>>1;
if(mid<ll)update(rs,mid+1,R,ll,rr);
else if(mid>=rr)update(ls,L,mid,ll,rr);
else update(ls,L,mid,ll,rr),update(rs,mid+1,R,ll,rr);
segtree[o]=segtree[ls]+segtree[rs];
}
int ask(int o,int L,int R,int ll,int rr){
if(L!=R)down(o,L,R);
if(L>=ll&&R<=rr)return segtree[o];
int mid=(L+R)>>1;
if(mid<ll)return ask(rs,mid+1,R,ll,rr);
else if(mid>=rr)return ask(ls,L,mid,ll,rr);
else return ask(ls,L,mid,ll,rr)+ask(rs,mid+1,R,ll,rr);
}
void work1(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
update(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
update(1,1,n,id[x],id[y]);
}
int work2(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
ans+=ask(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
ans+=ask(1,1,n,id[x],id[y]);
return ans;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<n;++i)scanf("%d%d",&f,&t),add(f,t),add(t,f);
dfs1(1,0),dfs2(1,1);
scanf("%d",&m);
for(int i=1;i<=m;++i){
int c;
scanf("%d%d%d",&c,&a,&b);
if(c==1)work1(a,b);
else printf("%d\n",work2(a,b));
}
return 0;
}