考虑将每一个同色块的答案保存在这一块深度最浅的那一个点(这是一个很好的思路),我们考虑如何维护即可,对于每一个点,我们维护f[now][0/1]表示当前点如果取白色/黑色,所在的子树中与这个点同色的联通块大小。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 101000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define MAXT MAXN*4
#define lch sgt[now].lc
#define rch sgt[now].rc
#define smid ((l+r)>>1)
#define INF 0x3f3f3f3f
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXV];
int tope=-1;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
int q[MAXN];
int pnt[MAXN];
int siz[MAXN];
int son[MAXN],top[MAXN],pos[MAXN],apos[MAXN],dfstime;
void bfs(int now)
{
int head=-1,tail=0;
Edge *ne;
q[0]=now;
pnt[now]=0;
while (head<tail)
{
now=q[++head];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
pnt[ne->np]=now;
q[++tail]=ne->np;
}
}
for (int i=tail;i>=0;i--)
{
now=q[i];
siz[now]=1;
int mxsiz=0;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
siz[now]+=siz[ne->np];
if (siz[ne->np]>mxsiz)
{
mxsiz=now;
son[now]=ne->np;
}
}
}
}
int stack[MAXN],tops=-1;
void dfs(int now)
{
Edge *ne;
stack[++tops]=now;
top[now]=now;
while (~tops)
{
now=stack[tops--];
pos[now]=++dfstime;
apos[dfstime]=now;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now] || ne->np==son[now])continue;
stack[++tops]=ne->np;
top[ne->np]=ne->np;
}
if (son[now])
{
stack[++tops]=son[now];
top[son[now]]=top[now];
}
}
}
int col[MAXN];
int ptra[MAXN];
struct sgt_node
{
int lc,rc;
int sum[2];
int pls[2];
int val[2];
}sgt[MAXT];
int topt=0;
void make_plus(int now,int c,int d)
{
sgt[now].val[c]+=d;
sgt[now].pls[c]+=d;
}
void down(int now)
{
if (sgt[now].pls[0])
{
make_plus(lch,0,sgt[now].pls[0]);
make_plus(rch,0,sgt[now].pls[0]);
sgt[now].pls[0]=0;
}
if (sgt[now].pls[1])
{
make_plus(lch,1,sgt[now].pls[1]);
make_plus(rch,1,sgt[now].pls[1]);
sgt[now].pls[1]=0;
}
}
int Build_sgt(int l,int r)
{
int now=++topt;
sgt[now].val[0]=sgt[now].val[1]=sgt[now].pls[0]=sgt[now].pls[1]=0;
sgt[now].sum[1]=1;
sgt[now].sum[0]=0;
if (l==r)
{
ptra[l]=now;
sgt[now].val[1]=siz[apos[l]];
sgt[now].val[0]=1;
return now;
}
lch=Build_sgt(l,smid);
rch=Build_sgt(smid+1,r);
return now;
}
pair<int,int> Query_sgt(int now,int l,int r,int pos)
{
if (l==r)
return make_pair(sgt[now].val[0],sgt[now].val[1]);
down(now);
if (pos<=smid)
return Query_sgt(lch,l,smid,pos);
else
return Query_sgt(rch,smid+1,r,pos);
}
void Modify_sgt(int now,int l,int r,int x,int y,int c,int d)
{
if (l==x && r==y)
{
make_plus(now,c,d);
return ;
}
down(now);
if (y<=smid)
return Modify_sgt(lch,l,smid,x,y,c,d);
else if (smid<x)
return Modify_sgt(rch,smid+1,r,x,y,c,d);
else
{
Modify_sgt(rch,smid+1,r,smid+1,y,c,d);
Modify_sgt(lch,l,smid,x,smid,c,d);
}
}
void Modify_sgt2(int now,int l,int r,int pos)
{
if (l==r)
return swap(sgt[now].sum[0],sgt[now].sum[1]);
down(now);
if (pos<=smid)
Modify_sgt2(lch,l,smid,pos);
else
Modify_sgt2(rch,smid+1,r,pos);
sgt[now].sum[0]=sgt[lch].sum[0]+sgt[rch].sum[0];
sgt[now].sum[1]=sgt[lch].sum[1]+sgt[rch].sum[1];
}
int Scan_sgt(int now,int l,int r,int x,int y,int c)
{
if (l==x && r==y)
{
if (sgt[now].sum[c]==(r-l+1))
{
return l;
}else if (sgt[now].sum[c]==0)
{
return -1;
}else
{
down(now);
int ret=Scan_sgt(rch,smid+1,r,smid+1,y,c);
if (ret==smid+1)
{
ret=Scan_sgt(lch,l,smid,x,smid,c);
if (ret==-1)return smid+1;
else return ret;
}else return ret;
}
}
down(now);
if (y<=smid)
return Scan_sgt(lch,l,smid,x,y,c);
else if (smid<x)
return Scan_sgt(rch,smid+1,r,x,y,c);
else
{
int ret=Scan_sgt(rch,smid+1,r,smid+1,y,c);
if (ret==smid+1)
{
ret=Scan_sgt(lch,l,smid,x,smid,c);
if (ret==-1)return smid+1;
else return ret;
}else return ret;
}
}
int spos[MAXN],tpos[MAXN];
int troot[MAXN];
int Swim_up(int x)
{
int rpos=pos[x];
int c=col[x];
while (x)
{
int y=Scan_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x],c);
if (y==-1)break;
else if (y!=pos[top[x]])
{
rpos=y;break;
}else
{
rpos=y;
x=pnt[top[x]];
}
}
return apos[rpos];
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m;
int x,y,z;
scanf("%d",&n);
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
bfs(1);
dfs(1);
for (int i=1;i<=n;i++)
spos[i]=INF,tpos[i]=-INF;
for (int i=1;i<=n;i++)
spos[top[i]]=min(spos[top[i]],pos[i]);
for (int i=1;i<=n;i++)
tpos[top[i]]=max(tpos[top[i]],pos[i]);
for (int i=1;i<=n;i++)
if (top[i]==i)
troot[i]=Build_sgt(spos[i],tpos[i]);
scanf("%d",&m);
int opt;
for (int i=1;i<=n;i++)col[i]=1;
for (int i=0;i<m;i++)
{
scanf("%d%d",&opt,&x);
if (opt==0)
{
int rpt=Swim_up(x);
pair<int,int> res=Query_sgt(troot[top[rpt]],spos[top[rpt]],tpos[top[rpt]],pos[rpt]);
if (col[x]==0)
printf("%d\n",res.first);
else
printf("%d\n",res.second);
}else
{
pair<int,int> res=Query_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x]);
int p=pnt[x];
int c=col[p];
int d,d2;
if (col[p]==1 && col[x]==1)d=-res.second,d2=res.first;
else if (col[p]==1 && col[x]==0)d=res.second,d2=-res.first;
else if (col[p]==0 && col[x]==1)d=res.first,d2=-res.second;
else d=-res.first,d2=res.second;
if (p)
{
sgt[ptra[pos[p]]].val[c^1]+=d2;
int a=Swim_up(p);
a=pnt[a];
if (!a)a=1;
while (true)
{
if (top[p]==top[a])
{
Modify_sgt(troot[top[a]],spos[top[a]],tpos[top[a]],pos[a],pos[p],c,d);
break;
}
Modify_sgt(troot[top[p]],spos[top[p]],tpos[top[p]],pos[top[p]],pos[p],c,d);
p=pnt[top[p]];
}
}
Modify_sgt2(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x]);
col[x]^=1;
}
}
}