SPOJ QTREE3Query on a tree again!(树链剖分+树状数组+二分)
题目大意
现在有一颗树,其所有的节点都为白色。有两种操作 ,一是将一个节点的颜色进行反转(即黑色变成白色,白色变成黑色),一是查询1号节点和v节点路径上深度最小的那个黑色节点
解题思路
设黑色的节点权值为1,白色的节点权值为0,对树进行剖分后用树状数组维护前缀和。对于每次查询,先找出节点v在上升到1号节点的路径上经过的所有的链的片段,对第一条和不为0的链的片段进行二分找出深度最小的点即可
AC代码
#include<bits/stdc++.h>
using namespace std;
const int size=4e5+5;
int head[size],nxt[size*2];
int to[size*2];
int dfn[size],fa[size],top[size];
int c[size],sz[size],son[size],dep[size];
int tot,cnt;
int a[size],opi[size];
inline int lowbit(int x) {return x&(-x);}
void init()
{
memset(head,-1,sizeof(head));
tot=0,cnt=0;
sz[0]=0,dep[0]=0;
memset(c,0,sizeof(c));
memset(a,0,sizeof(a));
}
void addedge(int u,int v)
{
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
void dfs1(int v,int f=0)
{
fa[v]=f;
dep[v]=dep[f]+1;
sz[v]=1;
son[v]=0;
for(int i=head[v];i!=-1;i=nxt[i])
{
if(to[i]==f) continue;
dfs1(to[i],v);
sz[v]=sz[to[i]]+sz[v];
if(sz[son[v]]<sz[to[i]]) son[v]=to[i];
}
}
void dfs2(int v,int f,int k)
{
top[v]=k;
dfn[v]=++cnt;
opi[cnt]=v;
if(son[v]!=0) dfs2(son[v],v,k);
for(int i=head[v];i!=-1;i=nxt[i])
{
if(to[i]==son[v]||to[i]==f) continue;
dfs2(to[i],v,to[i]);
}
}
void add(int x,int v)
{
for(int i=x;i<=cnt;i+=lowbit(i))
{
c[i]+=v;
}
}
int qsum(int x)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
vector<int> vec;
int qbtree(int v)
{
vec.clear();
int tv=v;
while(top[tv]!=1)
{
vec.push_back(top[tv]);
tv=fa[top[tv]];
}
vec.push_back(1);
int l=-1,r;
int bef;
for(int i=vec.size()-1;i>=0;i--)
{
if(i==0) bef=v;else bef=fa[vec[i-1]];
if(qsum(dfn[bef])-qsum(dfn[vec[i]]-1)>0)
{
l=dfn[vec[i]],r=dfn[bef];
break;
}
}
if(l==-1) return -1;
int basesum=qsum(l-1);
int ans=r;
while(l<=r)
{
int mid=(l+r)>>1;
if(qsum(mid)-basesum>0)
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return opi[ans];
}
int main()
{
int n,q;
//freopen("b.in","r",stdin);
while(~scanf("%d%d",&n,&q))
{
init();
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(1);
dfs2(1,0,1);
int op;int vx;
while(q--)
{
scanf("%d%d",&op,&vx);
if(op==0)
{
if(a[dfn[vx]]==0) add(dfn[vx],1),a[dfn[vx]]=1;
else add(dfn[vx],-1),a[dfn[vx]]=0;
}
else
{
printf("%d\n",qbtree(vx));
}
}
}
}