题意:

  一棵n个节点的树,节点有黑白两种颜色,初始均为白色。两种操作:1.更改一个节点的颜色;2.询问一个节点所处的颜色相同的联通块的大小。

思路:

  1.每个节点记录仅考虑其子树时,假设其为黑色时所处的黑色联通块的大小和假设其为白色时所处的白色联通块的大小(树状数组维护)。
  2.查询时找到深度最小的、与该点颜色相同的且两点之间的点颜色均与这两点相同(两点可以重合)(不妨称它为最远祖先)的答案。
  3.修改时应该修改该节点的父亲至最远祖先的父亲上的值。
  4.用树链剖分和树状数组维护。
  5.寻找最远祖先时,跳重链,树状数组维护当前颜色(0为白 1为黑),查询重链上的颜色和,判断是否整段相同。是则继续向上跳,否则二分祖先。

反思:

  1.越上面的dfn越小,二分开始打反了(二分看了Po姐的)
  2.树链剖分有些生疏,开始时打错死循了。树状数组的应用不熟练。
  3.开始时修改时是边找最远祖先边修改的,结果在根周围时出现了问题。
  4.根在修改、查询时都特判一下,重链的端点为最远祖先时也特判一下。

代码:

 #include<cstdio>
#define M 100005
#define swap(x,y) u=x,x=y,y=u
int n,u,cnt,dfn,p[M],v[M<<],id[M],co[M],sz[M],di[M],dep[M],top[M],hea[M],nex[M<<],ans[M][];
bool col[M]; void ins(int x,int y) { v[++cnt]=y,nex[cnt]=hea[x],hea[x]=cnt; }
void Add(int x,int y) { for (;x<=n;x+=x&-x) co[x]+=y; }
int Ask(int x) { int s=; for (;x;x-=x&-x) s=s+co[x]; return s; }
void add(int x,int y,bool c) { for (;x<=n;x+=x&-x) ans[x][c]+=y; }
int ask(int x,bool c) { int s=; for (;x;x-=x&-x) s=s+ans[x][c]; return s;}
bool pd(int x,int y,bool c)
{ return c && (Ask(y)-Ask(x-))==(y-x+) || (!c) && (Ask(x-)==Ask(y)); }
int read()
{
int x=; char ch=getchar();
for (;ch< || ch>;ch=getchar());
for (;ch> && ch<;ch=getchar()) x=(x<<)+(x<<)+ch-;
return x;
} void dfs(int x)
{
sz[x]=;
for (int i=hea[x],y;i;i=nex[i])
if ((y=v[i])^p[x]) p[y]=x,dep[y]=dep[x]+,dfs(y),sz[x]+=sz[y];
} void dfs(int x,int chain)
{
int i,k=,y;
top[x]=chain,id[x]=++dfn,di[dfn]=x;
for (i=hea[x];i;i=nex[i])
if ((y=v[i])^p[x] && sz[y]>sz[k]) k=y;
if (!k) return; dfs(k,chain);
for (i=hea[x];i;i=nex[i])
if ((y=v[i])^p[x] && y^k) dfs(y,y);
} void change(int x,int y,int v,bool c)
{
for (;top[x]!=top[y];x=p[top[x]])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
add(id[top[x]],v,c),add(id[x]+,-v,c);
}
if (dep[x]<dep[y]) swap(x,y);
add(id[y],v,c),add(id[x]+,-v,c);
} int find(int x,bool c)
{
int l,r,t,y,mid;
for (;x^;x=p[y])
{
l=id[y=top[x]],t=r=id[x];
if (!pd(l,r,c))
{
while (l+<r)
if (pd((mid=(l+r)>>),t,c)) r=mid; else l=mid+;
if (pd(l,t,c)) return l; return r;
}
if (col[p[y]]^c) return l;
}
return ;
} int main()
{
n=read(); int i,x,y,m;
for (i=;i<n;++i) x=read(),y=read(),ins(x,y),ins(y,x);
dfs(p[]=),dfs(,),add(,,);
for (i=;i<=n;++i) add(id[i],sz[i],),add(id[i]+,-sz[i],);
for (m=read();m--;)
{
i=read(),x=read();
if (i)
{
i=col[x];if (x-) change(p[x],p[di[find(x,i)]],-ask(id[x],i),i);
if (i) Add(id[x],-); else Add(id[x],); col[x]^=;
i=col[x];if (x-) change(p[x],p[di[find(x,i)]],ask(id[x],i),i);
}
else i=col[x],printf("%d\n",ask(find(x,i),i));
}
return ;
}

最新文章

  1. java日历显示年份、月份
  2. 如何区分/dev/input/event
  3. 蓝灯github地址
  4. mysql解决自动断开8小时未曾用过的链接
  5. RAPIDXML 中文手册,根据官方文档完整翻译!
  6. OWIN OAuth 2.0 Authorization Server
  7. 函数fseg_set_nth_frag_page_no
  8. php利用smtp类轻松的发送电子邮件
  9. 转:基于ASP.NET的Comet长连接技术解析
  10. C++虚基类详解(转)
  11. 一个关于poi导出的API
  12. 【Android Widget】1.TextView
  13. KBEngine WebConsole Guide
  14. tomcat 和 jboss access log 日志输出详解
  15. javascript实现有限状态机
  16. springboot整合springdata-jpa
  17. 题解-AtCoder Code-Festival2017 Final-J Tree MST
  18. [Linux] Linux的环境变量
  19. CentOS7 yum 安装 PHP 5.6.24
  20. webpack2.x抽取css

热门文章

  1. 二分图匹配 + 构造 E. Arpa’s overnight party and Mehrdad’s silent entering
  2. python_面向对象进阶(7)
  3. P1664 每日打卡心情好
  4. 使用原生javascript实现jquery的$(function(){ })
  5. 【转】Java集合:HashMap源码剖析
  6. Selenium2(WebDriver)开发环境搭建(java版)
  7. jQuery ajax参数后台获取不到的问题
  8. 洛谷 P2153 [SDOI2009]晨跑
  9. uva10366 Faucet Flow
  10. promise 里面的 console.info 打印信息 并不准确,后期有修改对象数据,会覆盖,影响之前的显示