题意

给你一棵\(n\)个点的树,编号\(1\)~\(n\)。每个点可以是黑色,可以是白色。初始时所有点都是黑色。有两种操作

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

\(1\ u\):翻转\(u\)的颜色

Sol

\(LCT\)做法:

黑白开两个\(LCT\)

然后有一个很\(Naive\)的做法

就是每次改颜色时,暴力枚举连的点,\(Link\)或\(Cut\)

显然菊花树直接就卡掉了

优化

把树定成一棵以\(1\)为根的有根树,然后把颜色放在它的父亲与它相连的边上

然后维护子树信息

\(Link\)或\(Cut\)就只涉及一条边

注意到每个子树的根不一定同色

询问时要特判根的颜色

就是\(Access\)一下,然后\(Splay\),跳左儿子找到根,并把它\(Splay\)

如果同色,就输出它的子树信息,否则输出它的右儿子的子树信息

应为右儿子深度比它大,所以,右儿子的子树信息就是答案

由于我们定义它是有根树

那么我们不能\(Makeroot\),这样的话才能保证能找到当前子树的根

那么\(Link\)时,为保证它父亲以上的点不受影响,\(Access\)并\(Splay\)它父亲

又因为它就是当前的子树的根,把它\(Splay\)一下,之后再连虚边

\(Cut\)时,把它\(Access\)并\(Splay\),那么它的父亲就在左子树,直接删掉它和它左儿子的实边是没有影响的

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5); IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} struct LCT{
typedef int Arr[_];
Arr fa, ch[2], sum, val; IL int Son(RG int x){
return ch[1][fa[x]] == x;
} IL int Isroot(RG int x){
return ch[0][fa[x]] != x && ch[1][fa[x]] != x;
} IL void Update(RG int x){
sum[x] = sum[ch[0][x]] + sum[ch[1][x]] + val[x] + 1;
} IL void Rotate(RG int x){
RG int y = fa[x], z = fa[y], c = Son(x);
if(!Isroot(y)) ch[Son(y)][z] = x; fa[x] = z;
ch[c][y] = ch[!c][x], fa[ch[c][y]] = y;
ch[!c][x] = y, fa[y] = x, Update(y);
} IL void Splay(RG int x){
for(RG int y = fa[x]; !Isroot(x); Rotate(x), y = fa[x])
if(!Isroot(y)) Son(x) ^ Son(y) ? Rotate(x) : Rotate(y);
Update(x);
} IL void Access(RG int x){
for(RG int y = 0; x; y = x, x = fa[x]){
Splay(x), val[x] += sum[ch[1][x]] - sum[y];
ch[1][x] = y, Update(x);
}
} IL int Findroot(RG int x){
Access(x), Splay(x);
while(ch[0][x]) x = ch[0][x];
Splay(x);
return x;
} IL void Link(RG int x, RG int y){
if(!y) return;
Access(y), Splay(x), Splay(y);
fa[x] = y, val[y] += sum[x], Update(y);
} IL void Cut(RG int x, RG int y){
if(!y) return;
Access(x), Splay(x);
ch[0][x] = fa[ch[0][x]] = 0, Update(x);
}
} T[2];
int fa[_], n, m, col[_];
vector <int> G[_]; IL void Dfs(RG int u, RG int ff){
for(RG int i = 0, l = G[u].size(); i < l; ++i){
RG int v = G[u][i];
if(v == ff) continue;
T[1].Link(v, u), fa[v] = u;
Dfs(v, u);
}
} int main(RG int argc, RG char *argv[]){
n = Input();
for(RG int i = 1; i <= n; ++i) col[i] = 1;
for(RG int i = 1; i < n; ++i){
RG int u = Input(), v = Input();
G[u].push_back(v), G[v].push_back(u);
}
Dfs(1, 0), m = Input();
for(RG int i = 1; i <= m; ++i){
RG int op = Input(), x = Input(), ff, &c = col[x];
if(op) T[c].Cut(x, fa[x]), c ^= 1, T[c].Link(x, fa[x]);
else{
T[c].Access(x), ff = T[c].Findroot(x);
if(col[ff] == c) printf("%d\n", T[c].sum[ff]);
else printf("%d\n", T[c].sum[T[c].ch[1][ff]]);
}
}
return 0;
}

SPOJ QTREE6的更多相关文章

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

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

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

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

  3. SPOJ QTREE6 lct

    题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #inc ...

  4. 【SPOJ】QTREE6(Link-Cut-Tree)

    [SPOJ]QTREE6(Link-Cut-Tree) 题面 Vjudge 题解 很神奇的一道题目 我们发现点有黑白两种,又是动态加边/删边 不难想到\(LCT\) 最爆力的做法,显然是每次修改单点颜 ...

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

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

  6. 【SPOJ】QTREE7(Link-Cut Tree)

    [SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...

  7. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  8. SPOJ DQUERY D-query(主席树)

    题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...

  9. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

随机推荐

  1. #PHP 数组添加元素、统计数组相同元素个数、改变数组key值~_~

    一.数组添加元素 1.定义和用法: array_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度. 2.语法: array_push(array,value1, ...

  2. maven 打包 源代码

    <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-sourc ...

  3. bzoj 4032(A的一个最短的子串,它不是B的子串 || A的一个最短的子串,它不是B的子序列 || A的一个最短的子序列,它不是B的子串||A的一个最短的子序列,它不是B的子序列)

    在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以不连续的一 ...

  4. 验证客户端的链接合法性和socketserver模块实现并发

    本节内容: 1.验证客户端的链接合法性 2.socketserver模块实现并发 一.验证客户端的链接合法性 首先,我们来探讨一下,什么叫验证合法性, 举个例子:有一天,我开了一个socket服务端, ...

  5. [转] vagrant系列(2):使用Vagrantfile实现集成预安装

    在我们的开发目录下,有一个文件Vagrantfile,里面包含有大量的配置信息,主要包括三个方面:虚拟机配置.SSH配置.基础配置.Vagrant是使用Ruby开发的,所以它的配置语法也是Ruby的, ...

  6. django笔记-model

    python manage.py sqlmigrate polls 打印人类可读格式

  7. 利用JS获取本地时间和服务器时间

    <p id="labTime"> <script type="text/javascript"> //取客户端时间 setInterva ...

  8. 汇编语言_实验四_[bx]和loop的使用

    四.实验结论 1.       实验内容1 (1)源代码: assume cs:code code segment mov ax,0b800h mov ds,ax mov bx,07b8h mov c ...

  9. Java学习之路(四):面向对象

    Java中的面向对象 概念:面向对象的原本的意思是“”万物皆对象“” 面向对象思想的特点: 是一种更符合我们思想习惯的思想,将复杂的事情简单化 使我们角色发生了转换,将我们从执行者变成了指挥者 面向对 ...

  10. C++析构函数(转)

    创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作(例如回收创建对象时消耗的各种资源),这个函数被称为析构函数. 析构函数(Destructor)也 ...