似乎是code chef上的题,不知为何bzoj也有。
题意:每个节点有颜色,刚开始可能是白色,每次修改一个点的颜色,或者询问一个点所在同色连通块的大小
此题考虑维护一个点只考虑其子树时,颜色为白色和黑色的连通块大小。
显然需要树链剖分+树状数组
然后询问就是跳到深度最小的跟它同色的祖先。
修改也是同理。
然后考虑怎么找到深度最小的同色祖先。
每次判断所在重链是否全为它的颜色。若是,就跳过,不是,就在链上二分查找位置。
时间复杂度o(nlogn^2)
#include <bits/stdc++.h>
#define gc getchar()
#define N 100009
#define inf 0x3f3f3f3f
#define ll long long
#define mid (l+r>>1)
using namespace std;
int n,first[N],number,m,fa[N],size[N],Mson[N],deep[N],top[N],cnt,dfn[N];
int bit[N][3],color[N],x,y,op,id[N];
//0:black 1:white
struct edge
{
int to,next;
void add(int x,int y)
{
to=y,next=first[x],first[x]=number;
}
}e[N<<1];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-'0';
while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';
return s*x;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y,int k)
{
for (;x<=n;x+=lowbit(x)) bit[x][k]+=y;
}
int qry(int x,int k,int ret=0)
{
for (;x;x-=lowbit(x)) ret+=bit[x][k];
return ret;
}
void dfs(int x)
{
size[x]=1;
deep[x]=deep[fa[x]]+1;
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=fa[x])
{
fa[e[i].to]=x;
dfs(e[i].to);
size[x]+=size[e[i].to];
if (size[e[i].to]>size[Mson[x]]) Mson[x]=e[i].to;
}
}
void Dfs(int x,int y)
{
id[dfn[x]=++cnt]=x;
top[x]=y;
if (Mson[x]) Dfs(Mson[x],y);
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=fa[x]&&e[i].to!=Mson[x]) Dfs(e[i].to,e[i].to);
}
void ins(int x,int y,int z,int k)
{
for (;top[x]!=top[y];x=fa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
add(dfn[top[x]],z,k),add(dfn[x]+1,-z,k);
}
if (deep[x]>deep[y]) swap(x,y);
add(dfn[x],z,k),add(dfn[y]+1,-z,k);
}
int get_anc(int x)
{
int c=color[x];
while (top[x]!=1)
{
int q=qry(dfn[x],2)-qry(dfn[top[x]]-1,2);
if (q==c*(dfn[x]-dfn[top[x]]+1))
{
if (color[fa[top[x]]]!=c) return top[x];
else x=fa[top[x]];
}
else
{
int l=dfn[top[x]],r=dfn[x],ret=0;
while (l<=r)
{
if (qry(r,2)-qry(mid-1,2)!=c*(r-mid+1))
l=mid+1;
else ret=mid,r=mid-1;
}
return id[ret];
}
}
int l=dfn[1],r=dfn[x],ret=0;
while (l<=r)
{
if (qry(r,2)-qry(mid-1,2)!=c*(r-mid+1))
l=mid+1;
else ret=mid,r=mid-1;
}
return id[ret];
}
int main()
{
n=read();
for (int i=1;i<n;i++)
x=read(),y=read(),e[++number].add(x,y),e[++number].add(y,x);
fa[1]=1;
dfs(1);
Dfs(1,1);
for (int i=1;i<=n;i++)
add(dfn[i],size[i],0),add(dfn[i]+1,-size[i],0);
add(1,1,1);
m=read();
for (int i=1;i<=m;i++)
{
op=read(),x=read();
if (op==0) printf("%d\n",qry(dfn[y=get_anc(x)],color[x]));
else
{
if (x>1) ins(fa[x],fa[y=get_anc(x)],-qry(dfn[x],color[x]),color[x]);
add(dfn[x],(color[x]^=1)?1:-1,2);
if (x>1) ins(fa[x],fa[y=get_anc(x)],qry(dfn[x],color[x]),color[x]);
}
}
return 0;
}