SP16549 QTREE6 - Query on a tree VI(LCT)
题意翻译
题目描述
给你一棵n个点的树,编号1~n。每个点可以是黑色,可以是白色。初始时所有点都是黑色。下面有两种操作请你操作给我们看:
0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥有相同的颜色
1 u:翻转u的颜色
输入格式
一行一个整数n
接下来n-1行,每行两个整数表示一条边
接下来一行一个整数m表示操作次数
接下来m行,每行两个整数分别表示操作类型和被操作节点 输出格式
对每个询问操作输出相应的结果
题解
简单来说,就是维护同色联通块的大小
干脆直接暴力linkcut好了(T上天)
然后来介绍一下(刚学会的)一种维护染色联通块的较为常用的模型
很多与树有关的题目,当边权不好处理时,可以把边权转化为儿子的点权来做
然后这里恰恰相反,要把点权给转化为边权
我们把每一个节点的颜色赋给与它父亲相连的边
弄两个LCT,对应两种颜色,一种颜色的边只有在对应的LCT中才会相连
于是,同色的联通块,就转化为了减去顶部节点后的边的连通块(因为顶部节点在这个LCT是没有向上连边的,说明顶部节点并不是这个颜色,那么他的所有子树并不连通,要断开才行)
然后可以发现,修改点的颜色之后,只要在原来的LCT中cut,在新的LCT上link就行啦
查询怎么做呢?先access,然后findroot,再输出root的实子树大小就行了
ps:1本来没有父亲,但为了方便,可以建一个虚点n+1,令他作为1的父亲就好了
//minamoto
#include<iostream>
#include<cstdio>
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=;
int f[N],Next[N<<],head[N],ver[N<<],tot,col[N],n,m;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
struct LCT{
int fa[N],ch[N][],si[N],sum[N];
LCT(){for(int i=;i<=n+;++i) sum[i]=;}
inline bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
#define lc ch[x][0]
#define rc ch[x][1]
inline void pushup(int x){sum[x]=sum[lc]+sum[rc]+si[x]+;}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][]==x;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][d^]]=y,ch[y][d]=ch[x][d^],ch[x][d^]=y,pushup(y);
}
void splay(int x){
for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
if(!isroot(y))
((ch[y][]==x)^(ch[z][]==y))?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x){
for(int y=;x;x=fa[y=x]){
splay(x);
si[x]+=sum[rc];
si[x]-=sum[rc=y];
}
}
int findroot(int x){
access(x),splay(x);
while(lc) x=lc;
splay(x);
return x;
}
void link(int x){
access(x),splay(x);
int y=fa[x]=f[x];
access(y),splay(y);
si[y]+=sum[x],sum[y]+=sum[x];
}
void cut(int x){
access(x),splay(x);
lc=fa[lc]=;
pushup(x);
}
}lct[];
void dfs(int u){
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v==f[u]) continue;
f[v]=u,dfs(v),lct[].link(v);
}
}
int main(){
//freopen("testdata.in","r",stdin);
n=read();
for(int i=;i<n;++i){
int u=read(),v=read();
add(u,v);
}
dfs();
f[]=n+,lct[].link();
m=read();
while(m--){
int op=read(),u=read();
if(op) lct[col[u]].cut(u),lct[col[u]^=].link(u);
else{
int v=lct[col[u]].findroot(u);
print(lct[col[u]].sum[lct[col[u]].ch[v][]]);
}
}
Ot();
return ;
}
SP16549 QTREE6 - Query on a tree VI(LCT)的更多相关文章
- 洛谷SP16549 QTREE6 - Query on a tree VI(LCT)
洛谷题目传送门 思路分析 题意就是要维护同色连通块大小.要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结. 至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次 ...
- SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块
\(\color{#0066ff}{ 题目描述 }\) 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v ...
- SP16580 QTREE7 - Query on a tree VII(LCT)
题意翻译 一棵树,每个点初始有个点权和颜色(输入会给你) 0 u:询问所有u,v路径上的最大点权,要满足u,v路径上所有点颜色相同 1 u:反转u的颜色 2 u w:把u的点权改成w 题解 Qtree ...
- QTREE5 - Query on a tree V(LCT)
题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...
- SP2666 QTREE4 - Query on a tree IV(LCT)
题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...
- QTREE6 - Query on a tree VI 解题报告
QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...
- [QTree6]Query on a tree VI
Description: 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括 ...
- SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」
题意 有操作 $0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色$1$ $u$:翻转 $u$ 的颜色 题解 直接用一个 $LCT$ 去暴力删边连 ...
- BZOJ3637 Query on a tree VI(树链剖分+线段树)
考虑对于每一个点维护子树内与其连通的点的信息.为了换色需要,记录每个点黑白两种情况下子树内连通块的大小. 查询时,找到深度最浅的同色祖先即可,这可以比较简单的树剖+线段树乱搞一下(似乎就是qtree3 ...
随机推荐
- Python shutil 模块学习笔记
学于https://automatetheboringstuff.com shutil 名字来源于 shell utilities,有学习或了解过Linux的人应该都对 shell 不陌生,可以借此来 ...
- strncmp memcmp区别
内部实现:前者逐每个字符进行比较,并判当前字符是否为0: 后者逐内存块进行比较. 效率:后者自然要优,不论从内部实现上,还是系统优化上. 场景:后者无法替代前者.在项目中遇到一种情况,两个字符串比较, ...
- 刷题向》关于一道比较优秀的递推型DP(openjudge9275)(EASY+)
先甩出传送门:http://noi.openjudge.cn/ch0206/9275/ 这道题比较经典, 最好不要看题解!!!!! 当然,如果你执意要看我也没有办法 首先,显然的我们可以用 f [ i ...
- css的优先级和权重问题 以及!important优先级
一,前言: 刚加的css怎么没有渲染出来?浏览器中查看,发现是被其他的css给覆盖了,相信我们都曾遇到过这样的问题.那么浏览器是如何选择css标签的渲染顺序的呢?换句话说,css选择器的优先级是怎么规 ...
- AlienWare
https://www.chiphell.com/thread-1705089-1-1.html AlienWare
- Solidity智能合约调用智能合约
来源:https://medium.com/@blockchain101/calling-the-function-of-another-contract-in-solidity-f9edfa921f ...
- Python OCR提取普通数字图形验证中的数字
截取图形验证码: # -*- coding: UTF-8 -*- ''' Created on 2016年7月4日 @author: xuxianglin ''' import os import t ...
- Java程序员常用工具类库 - 目录
有人说当你开始学习Java的时候,你就走上了一条不归路,在Java世界里,包罗万象,从J2SE,J2ME,J2EE三大平台,到J2EE中的13中核心技术,再到Java世界中万紫千红的Framework ...
- jqgrid 单元格放超链接文本
.前台 <%-- builed by manage.aspx.cmt [ver:] at // :: --%> <%@ Page Language="C#" Au ...
- BCompare 4重置试用天数
BCompare安装后有30天试用期,试用结束后,你可以卸载重装,以重新获得30天试用天数. BCompare的使用天数记录保存在注册表中,如果不想每次重装,也可删除对应的注册表值来重置激活天数. 命 ...