题意

有操作

$0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色
$1$ $u$:翻转 $u$ 的颜色

题解

直接用一个 $LCT$ 去暴力删边连边显然会 $T$

那么只有两个颜色的话就可以建两棵 $LCT$ ,观察到每次单点修改颜色时其子树所包含连通块在原颜色树上与其父亲所代表连通块断开,所以可以看作断开与父节点的边(实际上是点化边的思想),那么其它常规操作即可

注意要建个虚拟节点作为根节点的父亲

注意 $0$ 操作询问的输出,详细解释有在代码注释中给出

代码

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int MAXN = 1e06 + ;
const int MAXM = 1e06 + ; struct LinkedForwardStar {
int to; int next;
} ; LinkedForwardStar Link[MAXM << ];
int Head[MAXN]= {};
int size = ; void Insert (int u, int v) {
Link[++ size].to = v;
Link[size].next = Head[u]; Head[u] = size;
} int N, M;
int ances[MAXN]; struct Link_Cut_Tree {
int father[MAXN];
int son[MAXN][];
int subtree[MAXN], virsize[MAXN]; void init () {
for (int i = ; i <= N; i ++)
father[i] = son[i][] = son[i][] = subtree[i] = virsize[i] = ;
}
int isroot (int p) {
return son[father[p]][] != p && son[father[p]][] != p;
}
int sonbel (int p) {
return son[father[p]][] == p;
}
void pushup (int p) {
subtree[p] = subtree[son[p][]] + subtree[son[p][]] + virsize[p] + ;
}
void rotate (int p) {
int fa = father[p], anc = father[fa];
int s = sonbel (p);
son[fa][s] = son[p][s ^ ];
if (son[fa][s])
father[son[fa][s]] = fa;
if (! isroot (fa))
son[anc][sonbel (fa)] = p;
father[p] = anc;
son[p][s ^ ] = fa, father[fa] = p;
pushup (fa), pushup (p);
}
void splay (int p) {
for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p])
if (! isroot (fa))
sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p);
}
void Access (int p) {
for (int tp = ; p; tp = p, p = father[p]) {
splay (p);
virsize[p] += subtree[son[p][]];
son[p][] = tp;
virsize[p] -= subtree[son[p][]];
pushup (p);
}
}
int findroot (int p) {
Access (p), splay (p);
while (son[p][])
p = son[p][];
splay (p);
return p;
}
void link (int p) {
int fa = ances[p];
splay (p);
father[p] = fa;
Access (fa), splay (fa);
subtree[fa] += subtree[p], virsize[fa] += subtree[p];
}
void cut (int p) {
Access (p), splay (p);
father[son[p][]] = , son[p][] = ;
pushup (p);
}
} ;
Link_Cut_Tree LCT[]; void DFS (int root, int father) {
ances[root] = father;
LCT[].link (root);
for (int i = Head[root]; i; i = Link[i].next) {
int v = Link[i].to;
if (v == father)
continue;
DFS (v, root);
}
} int Colour[MAXN]= {}; int getnum () {
int num = ;
char ch = getchar (); while (! isdigit (ch))
ch = getchar ();
while (isdigit (ch))
num = (num << ) + (num << ) + ch - '', ch = getchar (); return num;
} int main () {
N = getnum ();
for (int i = ; i <= N; i ++)
LCT[].subtree[i] = LCT[].subtree[i] = ;
for (int i = ; i < N; i ++) {
int u = getnum (), v = getnum ();
Insert (u, v), Insert (v, u);
}
DFS (, N + );
M = getnum ();
for (int Case = ; Case <= M; Case ++) {
int opt = getnum (), p = getnum ();
int col = Colour[p];
if (opt == ) {
int anc = LCT[col].findroot (p);
printf ("%d\n", LCT[col].subtree[LCT[col].son[anc][]]);
// 注意,因为有可能存在两个不连通的连通快在LCT上连通,又在Access后右节点仅包含当前链
// 故需输出右子树信息而并非减一,否则有可能会算上另一个连通块的答案
}
else if (opt == )
LCT[col].cut (p), LCT[Colour[p] ^= ].link (p);
} return ;
} /*
5
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1
*/ /*
5
1 2
2 3
3 4
4 5
3
1 1
1 3
0 1
*/

SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」的更多相关文章

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

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

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

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

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

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

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

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

  5. [QTree6]Query on a tree VI

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

  6. 洛谷SP16549 QTREE6 - Query on a tree VI(LCT)

    洛谷题目传送门 思路分析 题意就是要维护同色连通块大小.要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结. 至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次 ...

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

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

  8. 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 ...

  9. QTREE6&&7 - Query on a tree VI &&VII

    树上连通块 不用具体距离,只询问连通块大小或者最大权值 可以类比Qtree5的方法,但是记录东西很多,例如子树有无0/1颜色等 一个trick,两个LCT分离颜色 每个颜色在边上. 仅保留连通块顶部不 ...

随机推荐

  1. Python - 静态函数(staticmethod), 类函数(classmethod), 成员函数 区别(完全解析)

    原文地址:http://blog.csdn.net/caroline_wendy/article/details/23383995 还有一篇:http://blog.csdn.net/carolzha ...

  2. 【BootStrap】Table的基本使用

    一.前言        新年新气象,转眼今年就28了,不知道今年能不能把妹成功呢?哈哈哈!上班第一天,部门Web技术主管给每个同事都发了红包鼓励大家今年加油,我作为新转入部门员工不能给团队掉链子,要加 ...

  3. CentOS安装oracleJDK

    实践证明,oracleJDK比openJDK快不止一星半点,换了之后立马从满负载降到个位数负载. 1.卸载openjdk # rpm -qa | grep -E '^(java|jdk)' # yum ...

  4. [Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法(转)

    [Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法http://blog.csdn.net/qiujuer/article/details/ ...

  5. Non-Local Image Dehazing 复现

    本文选自CVPR 2016, 文章链接Dana Berman, Tali Treibitz, Shai Avidan. Non-Local Image Dehazing 复现源码见我的Github 无 ...

  6. Docker数据管理(四)

    Docker数据管理 Docker数据分为两种: 数据卷 -v /data -v src:dst 数据卷容器 --volumes-from 数据卷 案例1:我们创建一个容器,起名叫nginx-volu ...

  7. AutoLayout中使用UIScrollView

    UIScrollView 在 Auto Layout 是一个很特殊的 view,对于 UIScrollView 的 subview 来说,它的 leading/trailing/top/bottom ...

  8. webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制

    webapi框架搭建系列博客 在上一篇的webapi框架搭建-安全机制(三)-简单的基于角色的权限控制,某个角色拥有哪些接口的权限是用硬编码的方式写在接口上的,如RBAuthorize(Roles = ...

  9. Spyder之Object Inspector组件

    Spyder之Object Inspector组件 最新版的Spyder已经把它修改为Help组件了. Quick access to documentation is a must for ever ...

  10. spring boot使用自定义配置的线程池执行Async异步任务

    一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context ...