洛谷题目传送门

思路分析

题意就是要维护同色连通块大小。要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结

至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次更改时暴力修改父边和子边。。。。。。

来个菊花图吧!(话说我真的好弱,前几天ZJOI的时候才知道对于某点度数很大的树/图有这样的称呼,真是很形象哈23333)

既然这条路行不通,那就换一种模型吧。

这是一种高级的维护染色连通块的较为通用的模型。

感觉蒟蒻对这种模型的理解与许多巨佬有不一样的地方,在这儿瞎扯扯吧

很多与树有关的题目,当边权不好处理时,有时候会转化为此边子节点的点权处理。

因为有根树中除了根,每个点都有唯一的父边。

在这一题里,道理是一样的,但转化方向却是反的,要把点化为边!

把每个点的父边赋予该点的颜色。我们需要两个LCT,每种对应一个颜色。一条边只有在对应颜色的LCT中才会被连上。

于是,原来同色点的连通块,就变成了剪开顶端节点后的边的连通块(解释一下,因为点的颜色给了父边,那么既然是顶端节点,那它的父边就不会在连通块中,也就是这个点与连通块不同色,于是该点的所有子树不能连起来,于是要剪掉)

然后就可以惊讶地发现,修改一个点的颜色之后,只要在原来颜色对应LCT中断掉父边,再在新颜色对应LCT中连接父边,就可以轻而易举地维护连通块啦。

再谈查询,上面提到了要剪开顶端节点(也就是连通块构成的树的树根),于是先findroot,再输出它的重子树的大小。

一个小细节,1节点是没有父亲的,不过为了模型的建立,要有父边,于是需要加一个虚点,让1的父亲指向它连边。

#include<cstdio>
#include<cstdlib>
#define R register int
#define I inline void
const int N=1000009,M=N<<1;
#define lc c[x][0]
#define rc c[x][1]
#define C col[u]
int fa[N],he[N],ne[M],to[M];
bool col[N];
struct LCT{
int f[N],c[N][2],si[N],s[N],h[N];
bool r[N];
LCT(){for(R i=1;i<N;++i)s[i]=1;}//注意初始化
inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
I pushup(R x){
s[x]=s[lc]+s[rc]+si[x]+1;
}
I rotate(R x){
R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
f[w]=y;f[y]=x;f[x]=z;
pushup(y);
}
I splay(R x){
R y;
while(nroot(x)){
if(nroot(y=f[x]))rotate((c[f[y]][0]==y)^(c[y][0]==x)?x:y);
rotate(x);
}
pushup(x);
}
I access(R x){
for(R y=0;x;x=f[y=x]){
splay(x);
si[x]+=s[rc];
si[x]-=s[rc=y];
}
}
inline int findroot(R x){
access(x);splay(x);
while(lc)x=lc;
splay(x);
return x;
}
I link(R x){//只传一个参数,因为只会连父边,cut同理
splay(x);//不用access(x),因为x一定是连通块的根
R y=f[x]=fa[x];
access(y);splay(y);//与常规LCT不同,别忘加
si[y]+=s[x];s[y]+=s[x];
}
I cut(R x){
access(x);splay(x);
lc=f[lc]=0;
pushup(x);
}
}lct[2];
void dfs(R x){
for(R y,i=he[x];i;i=ne[i])
if((y=to[i])!=fa[x])
fa[y]=x,dfs(y),lct[0].link(y);
}
#define G ch=getchar()
#define in(z) G;\
while(ch<'-')G;\
z=ch&15;G;\
while(ch>'-')z*=10,z+=ch&15,G
int main(){
register char ch;
R p=1,n,m,i,u,v,op;
in(n);
for(i=1;i<n;++i){
in(u);in(v);
to[++p]=v;ne[p]=he[u];he[u]=p;
to[++p]=u;ne[p]=he[v];he[v]=p;
}
dfs(1);
fa[1]=n+1;lct[0].link(1);//虚点
in(m);
while(m--){
in(op);in(u);
if(op)lct[C].cut(u),lct[C^=1].link(u);
else{
v=lct[C].findroot(u);
printf("%d\n",lct[C].s[lct[C].c[v][1]]);
}
}
return 0;
}

洛谷SP16549 QTREE6 - Query on a tree VI(LCT)的更多相关文章

  1. SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块

    \(\color{#0066ff}{ 题目描述 }\) 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v ...

  2. SP16549 QTREE6 - Query on a tree VI(LCT)

    题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...

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

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

  4. 洛谷SP16580 QTREE7 - Query on a tree VII(LCT,multiset)

    洛谷题目传送门 思路分析 维护子树最值还是第一次写QwQ 因为子树的最值会变化,所以不能简单地把最值记下来,还要维护一个平衡树,把每个子树的最大值扔进去,来资磁插入.删除和查询最值. 然后我就懒得手写 ...

  5. [QTree6]Query on a tree VI

    Description: 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括 ...

  6. SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」

    题意 有操作 $0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色$1$ $u$:翻转 $u$ 的颜色 题解 直接用一个 $LCT$ 去暴力删边连 ...

  7. SPOJ QTREE6 Query on a tree VI 树链剖分

    题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...

  8. bzoj3637 CodeChef SPOJ - QTREE6 Query on a tree VI 题解

    题意: 一棵n个节点的树,节点有黑白两种颜色,初始均为白色.两种操作:1.更改一个节点的颜色;2.询问一个节点所处的颜色相同的联通块的大小. 思路: 1.每个节点记录仅考虑其子树时,假设其为黑色时所处 ...

  9. 洛谷P2633/bzoj2588 Count on a tree (主席树)

    洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...

随机推荐

  1. odoo 打印格式中 打印第一个数据默认

    <table style="width:100%;"> <tr> <td style="word-wrap:break-word;width ...

  2. Scala--特质

    一.为什么没有多重继承 c++允许多重继承 Java不允许多重继承,类只能继承一个超类,可以实现任意数量的接口. 如何继承这两个抽象基类? Scala提供“特质”而非接口:特质可以同时抽象方法和具体方 ...

  3. MapReduce -- 最短路径

    示例: 给出各个节点到相邻节点的距离,要求算出初始节点到各个节点的最短路径. 数据: A (B,) (D,) B (C,) (D,) C (E,) D (B,) (C,) (E,) E (A,) (C ...

  4. 2.4《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——小结

    下Table 3本章重要命令小结 命令 描述 示例 > 将输出内容重定向到指定文件中 $ echo foo > foo.txt >> 将输出内容添加到指定问价中 $ echo ...

  5. 20155229《网络对抗技术》Exp2:后门原理与实践

    实验预习 后门: 指绕过安全控制而获取对程序或系统访问权的方法.最主要目的就是方便以后再次秘密进入或者控制系统. 木马与后门的区别: 木马:通过欺骗用户的方法(包含捆绑,利用网页等)让用户不知不觉的安 ...

  6. CMake与MSVC工程化实践

    CMake与MSVC工程化实践 CMake基础 cmake无疑是最流行的c++跨平台构建工具之一,关于cmake入门指南这里不再赘述,官方文档是最好的参考,这里通过一个例子简述构建一个工程常用的函数和 ...

  7. ngnix的基本安装及配置 centos7

    1.centos7  挂载ngnix的源 rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7- ...

  8. python之GIL理解

    GIL(Global Interpreter Lock) 全局解释器锁 python3中是假的多线程,它不是真正的并行,是利用了cpu上下文的切换而已.同一时间只能有一个线程使用共享数据,其它线程处于 ...

  9. 利用链式队列(带头节点)解决银行业务队列简单模拟问题(c++)-- 数据结构

    题目: 7-1 银行业务队列简单模拟 (30 分)   设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客 ...

  10. B1029 旧键盘 (20 分)

    20/20,第一次没调试就过了. #include<bits/stdc++.h> using namespace std; /* 1.standardize 2.put to the se ...