两种操作,第一种一条路径的边的颜色取反,第二种将一半在这条路径中的边的颜色取反,询问一条路径黑边的数量。
每条边上再添一个代表点表示这条边的颜色,那么第一种操作就可以直接把要操作的链取出来,再打个标记,第二种操作可以给每个点加一个标记,表示这个点的虚边连出去的儿子会要变一次颜色,然后再直接把lca的父亲节点变个颜色,可以看到,当access的时候只有有限条边会从虚变实或者从实变虚,此时用父亲节点的标记修改一下即可。
需要注意的是access的时候实变虚或者虚变实都要考虑到修改,然后还有两种操作在边界的直接修改操作。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int l[300000],r[300000],rt[300000],sum[300000],cl[300000],cl2[300000],bj[300000],sw[300000],sw2[300000];
int size[300000];
int tail[300000],next[1000000],sora[1000000];
int n,ss,m;
inline void updata(int x)
{
if (!x) return ;
sum[x]=sum[l[x]]+sum[r[x]]+cl[x]*bj[x];
size[x]=size[l[x]]+size[r[x]]+bj[x];
}
inline void swap(int x)
{
if (!x) return ;
sw[x]^=1;
cl[x]^=1;
sum[x]=size[x]-sum[x];
}
inline void swap2(int x)
{
if (!x) return ;
sw2[x]^=1;
cl2[x]^=1;
}
inline void pushdown(int x)
{
if (!x) return ;
if (sw[x]) {
if (l[x]) swap(l[x]);
if (r[x]) swap(r[x]);
sw[x]=0;
}
if (sw2[x]) {
if (l[x]) swap2(l[x]);
if (r[x]) swap2(r[x]);
sw2[x]=0;
}
}
inline void right(int x)
{
int y=rt[x],z=rt[y];
l[y]=r[x],rt[r[x]]=y;
r[x]=y,rt[y]=x;
if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;
rt[x]=z;
updata(y);
}
inline void left(int x)
{
int y=rt[x],z=rt[y];
r[y]=l[x],rt[l[x]]=y;
l[x]=y,rt[y]=x;
if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;
rt[x]=z;
updata(y);
}
inline void splay(int x)
{
if (!x) return ;
pushdown(x);
for (int y,z;l[rt[x]]==x || r[rt[x]]==x;) {
y=rt[x],z=rt[y];
if (l[z]==y || r[z]==y) pushdown(z);
pushdown(y),pushdown(x);
if (l[y]==x) {
if (l[z]==y) right(y);
right(x);
}
else if (r[y]==x) {
if (r[z]==y) left(y);
left(x);
}
}
updata(x);
}
inline void access(int x)
{
if (!x) return ;
bool flag=(x==2);
splay(x);
int tmp;
for (tmp=l[x];r[tmp];tmp=r[tmp]) ;
l[x]=0,updata(x);
if (tmp) splay(tmp),cl[tmp]^=(cl2[x]*(!bj[x])),updata(tmp);
for (;rt[x];) {
int y=rt[x];
splay(y);
int tmp;
for (tmp=x;r[tmp];tmp=r[tmp]) ;
splay(tmp);
cl[tmp]^=(cl2[y]*(!bj[y])),updata(tmp);
tmp=l[y];
for (;r[tmp];tmp=r[tmp]) ;
// if (flag) cout<<tmp<<' '<<y<<endl;
if (tmp) {
splay(tmp);
cl[tmp]^=(cl2[y]*(!bj[y])),updata(tmp);
}
splay(x),splay(y);
l[y]=x,updata(y);
splay(x);
}
}
void origin()
{
ss=n+n;
for (int i=0;i<=n+n;i++) {
l[i]=r[i]=rt[i]=sum[i]=bj[i]=0;
sw[i]=sw2[i]=cl[i]=cl2[i]=size[i]=0;
tail[i]=i,next[i]=0;
}
for (int i=1;i<=n;i++) bj[i]=0;
for (int i=1;i<=n;i++) bj[i+n]=1;
}
void dfs(int x,int y)
{
rt[x]=y;
for (int i=x,ne;next[i];) {
i=next[i],ne=sora[i];
if (ne!=y) dfs(ne,x);
}
}
void link(int x,int y)
{
++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,next[ss]=0;
}
int asklca(int x,int y)
{
access(x),access(y);
splay(x);
if (rt[x]==0) return x;
return rt[x];
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int t;
scanf("%d",&t);
for (;t;t--) {
scanf("%d",&n);
origin();
for (int i=1;i<=n-1;i++) {
int x,y;
scanf("%d%d",&x,&y);
link(x,n+i);
link(n+i,y);
}
dfs(1,0);
scanf("%d",&m);
for (int i=1;i<=m;i++) {
int c,L,R;
scanf("%d%d%d",&c,&L,&R);
int lca=asklca(L,R);
// cout<<L<<' '<<R<<' '<<lca<<endl;
if (L==lca) swap(L,R);
if (1==c) {
if (L==R) continue;
if (R==lca) {
access(L);
access(lca);
splay(L),swap(L);
continue;
}
access(L);
access(R);
access(lca);
splay(R),swap(R);
splay(L),swap(L);
}
else if (2==c) {
if (L==R) {
access(L);
splay(L);
// swap2(L);
cl2[L]^=1,updata(L);
int tmp=r[L];
for (;l[tmp];tmp=l[tmp]) ;
splay(tmp);
cl[tmp]^=1,updata(tmp);
continue;
}
if (R==lca) {
access(L);
access(lca);
splay(L),swap2(L);
splay(lca),cl2[lca]^=1,updata(lca);
int tmp=r[lca];
for (;l[tmp];tmp=l[tmp]) ;
if (tmp) {
splay(tmp);
cl[tmp]^=1,updata(tmp);
}
splay(L),tmp=r[L];
for (;r[tmp];tmp=r[tmp]) ;
if (tmp) {
splay(tmp);
cl[tmp]^=1,updata(tmp);
}
continue;
}
access(L);
access(R);
access(lca);
splay(R),swap2(R);
splay(L),swap2(L);
splay(lca),cl2[lca]^=1,updata(lca);
int tmp=r[lca];
for (;l[tmp];tmp=l[tmp]) ;
if (tmp) {
splay(tmp);
cl[tmp]^=1,updata(tmp);
}
splay(L),tmp=r[L];
for (;r[tmp];tmp=r[tmp]) ;
if (tmp) {
splay(tmp);
cl[tmp]^=1,updata(tmp);
}
splay(R),tmp=r[R];
for (;r[tmp];tmp=r[tmp]) ;
if (tmp) {
splay(tmp);
cl[tmp]^=1,updata(tmp);
}
}
else if (3==c) {
if (L==R) {
printf("0\n");
continue;
}
if (R==lca){
access(L);
access(lca);
splay(L);
int tmp=L;
for (;r[tmp];tmp=r[tmp]) ;
splay(tmp);
int ans=sum[tmp]-cl[tmp]+(cl[tmp]^cl2[lca]);
printf("%d\n",ans);
continue;
}
access(L);
access(R);
access(lca);
splay(L),splay(R),splay(lca);
for (;r[L];L=r[L]) ;splay(L);
for (;r[R];R=r[R]) ;splay(R);
// cout<<L<<' '<<R<<' '<<cl[L]<<' '<<cl[R]<<endl;
// cout<<sum[L]<<' '<<sum[R]<<endl;
int ans=sum[L]+sum[R]-cl[L]-cl[R]+(cl[L]^cl2[lca])+(cl[R]^cl2[lca]);
printf("%d\n",ans);
}
}
}
return 0;
}