1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| int deep[N],son[N],siz[N],fa[N],top[N],id[N],cnt; vector<int> g[N]; int n,m,rt=1,cnt1; void dfs0(int now,int father){ deep[now]=deep[father]+1; fa[now]=father; siz[now]=1; for(auto &i:g[now]){ if(i==father)continue; dfs0(i,now); siz[now]+=siz[i]; if(siz[i]>siz[son[now]])son[now]=i; } } void dfs1(int now,int tp){ top[now]=tp,id[now]=++cnt; if(son[now]==0){ return; } dfs1(son[now],tp); for(auto &i:g[now]){ if(i==fa[now]||i==son[now])continue; dfs1(i,i); } } struct node{ int pre,suf,num; }tree[N*4]; int tag[N*4]; void pushup(int u){ tree[u].pre=tree[lb].pre; tree[u].suf=tree[rb].suf; tree[u].num=tree[lb].num+tree[rb].num+(tree[lb].suf==tree[rb].pre); } void build(int now,int l,int r){ if(l==r){tree[now]={++cnt1,cnt1,0};return;} int mid=(l+r)>>1; build(now*2,l,mid); build(now*2+1,mid+1,r); pushup(now); } void change(int x,int len,int val){ tag[x]=val; tree[x]={val,val,len-1}; } void pushdown(int u,int l,int r){ if(tag[u]){ int mid=(l+r)>>1; change(lb,mid-l+1,tag[u]); change(rb,r-mid,tag[u]); tag[u]=0; } }
void update(int u,int left,int right,int l,int r,int val){ if(l<=left&&right<=r){ change(u,right-left+1,val); }else if(!(r<left||right<l)){ int mid=(left+right)>>1; pushdown(u,left,right); update(lb,left,mid,l,r,val); update(rb,mid+1,right,l,r,val); pushup(u); } } node query(int u,int left,int right,int l,int r){ if(l<=left&&right<=r){ return tree[u]; }else if(!(r<left||l>right)){ int mid=(left+right)>>1; pushdown(u,left,right); if(r<=mid){return query(lb,left,mid,l,r);} elif(l>mid){return query(rb,mid+1,right,l,r);} else{ auto lx=query(lb,left,mid,l,r),rx=query(rb,mid+1,right,l,r); node ret; ret.pre=lx.pre; ret.suf=rx.suf; ret.num=lx.num+rx.num+(lx.suf==rx.pre); return ret; } }else return (node){-1,-1,0}; } int query_point(int u,int l,int r,int pos){ if(l==r)return tree[u].pre; int mid=l+r>>1; pushdown(u,l,r); if(pos<=mid)return query_point(lb,l,mid,pos); else return query_point(rb,mid+1,r,pos); } int querypath(int u,int v){ int ret=0; while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]]){swap(u,v);} auto tmp=query(1,1,n,id[top[u]],id[u]); ret+=(tmp.num+(query_point(1,1,n,id[top[u]])==query_point(1,1,n,id[fa[top[u]]]))); u=fa[top[u]]; } if(deep[u]<deep[v]){swap(u,v);} auto tmp=query(1,1,n,id[v],id[u]); ret=ret+tmp.num; return ret; } void updatepath(int u,int v,int k){ while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]])swap(u,v); update(1,1,n,id[top[u]],id[u],k); u=fa[top[u]]; } if(deep[u]<deep[v])swap(u,v); update(1,1,n,id[v],id[u],k); }
signed main(){ int t=read(); while(t--){ n=read();int q=read(); cnt=0; cnt1=0; for(int i=0;i<N;++i)tag[i]=0; for(int i=1;i<=n;++i){ g[i].clear(); son[i]=0;siz[i]=0; } for(int i=1;i<n;++i){ int u=read(),v=read(); g[u].push_back(v); g[v].push_back(u); } dfs0(rt,0); dfs1(rt,rt); build(1,1,n); while(q--){ int opt=read(),u=read(),v=read(); if(opt==1){ updatepath(u,v,++cnt1); }else{ printf("%lld\n",querypath(u,v)); } } } }
|