【SPOJ QTREE6】Query on a tree VI(LCT维护树上同色连通块)

摘要:
树上同色连通块容易想到去建两棵树,分别代表黑点和白点。这里就有一个很巧妙的思路,既然我们有两棵树,干脆对于每个点分别维护好它是黑色/白色时,以它为最浅点的连通块信息。此题要求同色连通块大小,也就是要维护子树大小,是的一个经典操作,注意维护虚儿子子树大小之和即可。x:f),0),Ro;PU;}IvoidAc{forS,O[x].G+=O[O[x].S[1]].Sz-O[y].Sz,O[x].S[1]=y,PU;}public:IvoidInit(){forO[i].Sz=O[i].G=1;}//每个点自己的大小一同记在虚儿子子树大小之和中IvoidLink{Ac,S,S,O[y].F=x,O[x].G+=O[y].Sz,PU;}//连边IvoidCut{Ac,S,O[x].S[1]=O[y].F=0,PU;}//断边IintQ{Ac,S;Wx=O[x].S[0];returnS,O[O[x].S[1]].Sz;}//Access并Splay根,询问根节点右儿子信息}LCT[2];intfa[N+5];Ivoiddfs//预处理建树{fore[i].to^fa[x]&&;LCT[0].Link;}intmain(){RIi,x,y;forread(x,y),add(x,y),add(y,x);LCT[0].Init(),LCT[1].Init(),fa[1]=n+1,dfs;//给根节点建个父节点RIQt;read;Wread(x,y),x?

点此看题面

  • 给定一棵(n)个点的树,初始所有点为黑色。
  • 要求支持两种操作:询问一个点所在同色连通块大小;翻转一个点的颜色。
  • (n,qle10^5)

树上同色连通块

容易想到去建两棵树,分别代表黑点和白点。

一开始可能会很无脑地去想改变颜色就直接在原树上断边,新树上连边,但由于一个点的子节点可能有一大堆,复杂度爆炸。

这里就有一个很巧妙的思路,既然我们有两棵树,干脆对于每个点分别维护好它是黑色/白色时,以它为最浅点的连通块信息(其他点就看作真实颜色)。

这样一来,一大好处就是我们修改一个点的时候不需要再管它和儿子间的关系,只需要在对应的树中连上/断开它与父节点之间的边。

而要询问(x)所在同色连通块的信息,首先(Access(x)),由于根节点必然是一个异色点(同色点会向父节点连边),因此我们(Splay)根节点,则此时根节点右儿子的子树信息就是我们要求的连通块信息了。

这里注意一个细节问题,原树的根节点是没有父节点的,我们要给它建一个,否则询问时就始终会被当作异色点舍掉。

此题要求同色连通块大小,也就是要维护子树大小,是(LCT)的一个经典操作,注意维护虚儿子子树大小之和即可。

代码:(O(nlogn))

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,a[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[2*N+5];
namespace FastIO
{
	#define FS 100000
	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
');}
}using namespace FastIO;
class LinkCutTree
{
	private:
		#define PU(x) (O[x].Sz=O[O[x].S[0]].Sz+O[O[x].S[1]].Sz+O[x].G)//上传信息
		#define IR(x) (O[O[x].F].S[0]^x&&O[O[x].F].S[1]^x)
		#define Wh(x) (O[O[x].F].S[1]==x)
		#define Co(x,y,d) (O[O[x].F=y].S[d]=x)
		struct node {int Sz,G,F,S[2];}O[N+5];
		I void Ro(RI x) {RI f=O[x].F,p=O[f].F,d=Wh(x);
			!IR(f)&&(O[p].S[Wh(f)]=x),O[x].F=p,Co(O[x].S[d^1],f,d),Co(f,x,d^1),PU(f);}
		I void S(RI x) {RI f;W(!IR(x)) f=O[x].F,!IR(f)&&(Ro(Wh(x)^Wh(f)?x:f),0),Ro(x);PU(x);}
		I void Ac(RI x) {for(RI y=0;x;x=O[y=x].F) S(x),O[x].G+=O[O[x].S[1]].Sz-O[y].Sz,O[x].S[1]=y,PU(x);}
	public:
		I void Init() {for(RI i=1;i<=n;++i) O[i].Sz=O[i].G=1;}//每个点自己的大小一同记在虚儿子子树大小之和中
		I void Link(CI x,CI y) {Ac(x),S(x),S(y),O[y].F=x,O[x].G+=O[y].Sz,PU(x);}//连边
		I void Cut(CI x,CI y) {Ac(y),S(x),O[x].S[1]=O[y].F=0,PU(x);}//断边
		I int Q(RI x) {Ac(x),S(x);W(O[x].S[0]) x=O[x].S[0];return S(x),O[O[x].S[1]].Sz;}//Access(x)并Splay根,询问根节点右儿子信息
}LCT[2];
int fa[N+5];I void dfs(CI x)//预处理建树
{
	for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^fa[x]&&(fa[e[i].to]=x,dfs(e[i].to),0);LCT[0].Link(fa[x],x);
}
int main()
{
	RI i,x,y;for(read(n),i=1;i^n;++i) read(x,y),add(x,y),add(y,x);LCT[0].Init(),LCT[1].Init(),fa[1]=n+1,dfs(1);//给根节点建个父节点
	RI Qt;read(Qt);W(Qt--) read(x,y),x?(LCT[a[y]].Cut(fa[y],y),LCT[a[y]^=1].Link(fa[y],y)):writeln(LCT[a[y]].Q(y));//翻转只需考虑与父节点的连边
	return clear(),0;
}

免责声明:文章转载自《【SPOJ QTREE6】Query on a tree VI(LCT维护树上同色连通块)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Asp.net mvc与PHP的Session共享的实现“爆打”团队阿尔法发布 以及 第四周任务下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

office 2016 专业版 删除部分组件

删除Office2016 Professional Edition####1中的一些组件。打开控制面板。2.单击此选项。3.找到Office2016并右键单击以选择更改。4.选择并确认。5.选择要删除的组件(以Access为例)。6.单击此处。7.单击“继续”。8.等等。9.完成此方法并不是真正删除模块。这意味着模块已禁用。如果您想在将来重新启用它,请重复前...

VMP加壳(三):VMP壳爆破实战-破解某编辑类软件

同时,记住在内存视图中向VMP0段提供断点后继续单击确认按钮,以查看调用方法的位置(此处的返回地址为0x5E01E9),但此处返回push(或vm条目)。这个地方会是验证码检测的入口吗!通过字符串查找各种键提示(sn、不正确注册等)的内存:通过访问断点查找键代码,然后找出调用该函数的函数,这与JCC指令的距离更远。...

C#基础系列过滤器与特性

过滤器和特性结合在一起,在方法上优雅地使用过滤器。3.在过滤器中,。NETFrameWork提供了两种类型:一种是提供给ASP的筛选器。NETMVC在命名空间下使用System.Web。另一个是提供给ASP的过滤器。NETWebApi在命名空间下使用System.Web.Http.Filters。这两种类型不能混合使用,否则无法拦截并生效。...

SpringBoot入门 (三) 日志配置

上一篇博客文章记录了在spring-boot项目中读取的属性文件中配置的属性。本文将学习如何登录springboot项目。SpringBoot在内部使用CommonsLogging进行日志记录,但它也为其他日志记录框架提供默认配置,如JavautilLogging、Log4j2和Logback。在每种情况下,日志记录器都预先配置为使用控制台输出和可选文件输出...

scan chain的原理和实现——5.UDTP

UDTP(用户定义的测试点)指示DFTC在设计中用户指定的位置插入控制点和观察点。1.为什么使用UDTP?修复不可控的时钟和/或异步输入;增加设计的测试覆盖率;减少模式数量2.UDTP类型① 力0、力1、力01、力z0、力z1、力z01②控制_ 0...

jquery跨域请求数据

Jquery跨域请求数据Jquery跨请求数据。事实上,这很容易。请遵循以下步骤:首先,编写js,通过get获取远程数据。请注意,回调参数应添加在链接之后,这意味着将回调函数地址传输到远程页面。',{params},函数cb{alert;alert;},'json');第二:编写处理程序。publicvoidProcessRequest{context.Re...