传送门

题意简述:给你一棵nnn个黑白点的树,支持改一个点的颜色,询问跟某个点颜色相同的连通块大小。


思路:

还是链分治 233

记fi,0/1f_{i,0/1}fi,0/1​表示iii的所有颜色为0/10/10/1的轻儿子在它们子树中颜色相同的连通块大小。

然后这个可以用来询问子树里的答案,但是要询问的东西是针对全局的。

因此我们沿着重链往上跳更新答案,直到某条链中有点跟要问的颜色不一样。

即fif_ifi​表示这个东西:



对于这棵树,我们的fB1,0f_{B1,0}fB1,0​就等于跟它颜色一样的B2B2B2的子树中颜色为BBB且与B2B2B2连通的连通块大小,即111

而对于fB1,1f_{B1,1}fB1,1​由于他的颜色不是WWW,因此fB1,1=0f_{B1,1}=0fB1,1​=0。

对于B3B3B3假设重儿子是W3W3W3,那么fB3,0=1+1=2,fB3,1=0f_{B3,0}=1+1=2,f_{B3,1}=0fB3,0​=1+1=2,fB3,1​=0

这样子就可以用链分治维护要有的信息了。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int N=1e5+5;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(((ans<<2)+ans)<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef pair<int,int> pii;
int n,m,fa[N],top[N],bot[N],num[N],pred[N],siz[N],hson[N],tot=0,f[N][2];
vector<int>e[N];
bool col[N];
void dfs1(int p){
	siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa[p])continue;
		fa[v]=p,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
void dfs2(int p,int tp){
	top[p]=tp,bot[tp]=p,pred[num[p]=++tot]=p;
	if(!hson[p])return;
	dfs2(hson[p],tp);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa[p]||v==hson[p])continue;
		dfs2(v,v);
	}
}
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (T[p].l+T[p].r>>1)
	struct Val{
		int ls,rs;
		bool f;
		inline void init(const int&x){ls=rs=x;f=x==0?0:1;}
	};
	struct Node{int l,r;Val s[2];}T[N<<2];
	inline Val operator+(const Val&a,const Val&b){
		Val ret;
		ret.f=a.f&b.f;
		ret.ls=a.ls+(a.f?b.ls:0);
		ret.rs=b.rs+(b.f?a.rs:0);
		return ret;
	}
	inline void pushup(int p){
		T[p].s[0]=T[lc].s[0]+T[rc].s[0];
		T[p].s[1]=T[lc].s[1]+T[rc].s[1];
	}
	inline void Set(int p){
		int k=pred[T[p].l];
		T[p].s[col[k]].init(f[k][col[k]]+1);
		T[p].s[col[k]^1].init(0);
	}
	inline void build(int p,int l,int r){
		T[p].l=l,T[p].r=r;
		if(l==r)return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void update(int p,int k){
		if(T[p].l==T[p].r)return Set(p);
		update(k<=mid?lc:rc,k),pushup(p);
	}
	inline Val query(int p,int ql,int qr,bool f){
		if(ql<=T[p].l&&T[p].r<=qr)return T[p].s[f];
		if(qr<=mid)return query(lc,ql,qr,f);
		if(ql>mid)return query(rc,ql,qr,f);
		return query(lc,ql,qr,f)+query(rc,ql,qr,f);
	}
}
pii dfs3(int tp){
	for(ri p=tp;p;p=hson[p]){
		for(ri i=0,v;i<e[p].size();++i){
			if((v=e[p][i])==fa[p]||v==hson[p])continue;
			pii tmp=dfs3(v);
			f[p][0]+=tmp.fi,f[p][1]+=tmp.se;
		}
		SGT::update(1,num[p]);
	}
	return pii(SGT::query(1,num[tp],num[bot[tp]],0).ls,SGT::query(1,num[tp],num[bot[tp]],1).ls);
}
inline void update(int p){
	int ft,tp,bt;
	while(p){
		ft=fa[top[p]],tp=top[p],bt=bot[tp];
		if(ft){
			pii tmp=pii(SGT::query(1,num[tp],num[bt],0).ls,SGT::query(1,num[tp],num[bt],1).ls);
			f[ft][0]-=tmp.fi,f[ft][1]-=tmp.se;
		}
		SGT::update(1,num[p]);
		if(ft){
			pii tmp=pii(SGT::query(1,num[tp],num[bt],0).ls,SGT::query(1,num[tp],num[bt],1).ls);
			f[ft][0]+=tmp.fi,f[ft][1]+=tmp.se;
		}
		p=ft;
	}
}
inline int query(int p){
	int ft,tp,bt,ret=0,x=p;
	SGT::Val tmp;
	while(p){
		if(col[x]^col[p])break;
		ft=fa[top[p]],tp=top[p],bt=bot[tp];
		ret=SGT::query(1,num[p],num[bt],col[x]).ls;
		if(p^tp){
			tmp=SGT::query(1,num[tp],num[p]-1,col[x]),ret+=tmp.rs;
			if(!tmp.f)return ret;
		}
		p=ft;
	}
	return ret;
}
int main(){
	n=read();
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	dfs1(1),dfs2(1,1),SGT::build(1,1,n),dfs3(1);
	for(ri tt=read(),x;tt;--tt){
		if(read())col[x=read()]^=1,update(x);
		else cout<<query(read())<<'\n';
	}
	return 0;
}

2019.02.17 spoj Query on a tree VI(链分治)的更多相关文章

  1. 2019.02.17 spoj Query on a tree VII(链分治)

    传送门 跟QTREE6QTREE6QTREE6神似,改成了求连通块里的最大值. 于是我们对每条链开一个heapheapheap维护一下即可. MDMDMD终于1A1A1A链分治了. 代码: #incl ...

  2. 2019.02.17 spoj Query on a tree V(链分治)

    传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...

  3. 2019.02.16 spoj Query on a tree IV(链分治)

    传送门 题意简述: 捉迷藏强化版(带有边权,可以为负数) 思路:好吧这次我们不用点分树,我们用听起来更屌的链分治. 直接把树剖成若干条重链,这样保证从任意一个点跳到根节点是不会跳超过logloglog ...

  4. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  5. bzoj 3637: Query on a tree VI 树链剖分 && AC600

    3637: Query on a tree VI Time Limit: 8 Sec  Memory Limit: 1024 MBSubmit: 206  Solved: 38[Submit][Sta ...

  6. QTREE6 - Query on a tree VI 解题报告

    QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...

  7. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

  8. spoj 375 Query on a tree (树链剖分)

    Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...

  9. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

随机推荐

  1. [UE4]Background Blur,背景模糊

    一.Blur Strength:模糊强度 二.背景是模糊的,在Background Blur前面的控件二不会模糊. 三.可以调整顺序,让按钮也模糊.然后按钮被模糊了,但是按钮还可以被点击的,Backg ...

  2. k8s学习笔记之二:使用kubeadm安装k8s集群

    一.集群环境信息及安装前准备 部署前操作(集群内所有主机): .关闭防火墙,关闭selinux(生产环境按需关闭或打开) .同步服务器时间,选择公网ntpd服务器或者自建ntpd服务器 .关闭swap ...

  3. html 设置input框的记忆功能(联想内容)

    autocomplete=“on/off” 1.默认情况下,autocomplete的值是on.你可以将其设置为off. 2.autocomplete属性可以放在input 元素上,也可以放在form ...

  4. CentOS7 YUM安装与配置 MySQL5.7

    原文链接:http://blog.csdn.net/xyang81/article/details/51759200 安装环境:CentOS7 64位,MySQL5.7 1.配置YUM源 在MySQL ...

  5. Android 开发 系统组件集合

    常用的TextView.Button.ImageView和几个常用布局就不介绍了,我们介绍一些特别好用但是常常忘记的组件. 标题栏组件 <androidx.appcompat.widget.To ...

  6. 【学习】通用函数:快速的元素级数组函数【Numpy】

    通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数.可以将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器. sqrt 和 exp为一元(unary ...

  7. Python实践练习:强口令检测

    题目: 写一个函数,它使用正则表达式,确保传入的口令字符串是强口令.强口令的定义是:长度不少于 8 个字符,同时包含大写和小写字符,至少有一位数字.你可能需要用多个正则表达式来测试该字符串,以保证它的 ...

  8. centos 7设置本地yum资源库

    前言 同样的,是在这两天安装ambari的时候遇到的问题之一,那就是关于centos的本地yum源的制作,当时是一种是制作iso镜像的yum源,还有一种将rpm软件包打成压缩包上传到centos的某一 ...

  9. 使用swiper插件,隐藏swiper后再显示,不会触发自动播放的解决办法

    问题: 项目中有一个需求,当点击P1时,两个页面进行轮播.当点击P2时,页面不轮播. 设置好以后,点击P2,再点击P1,此时页面不能自动轮播,只能手动触发. 解决: 在轮播器配置里,配置observe ...

  10. oracle 连接字符串的问题

    未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息.数据类型不被支持. 原因是你用的ADO   for   ORACLE的驱动是微软的Microsoft OLE DB ...