\(\color{#0066ff}{ 题目描述 }\)

给你一棵n个点的树,编号1~n。每个点可以是黑色,可以是白色。初始时所有点都是黑色。下面有两种操作请你操作给我们看:

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

\(\color{#0066ff}{输入格式}\)

一行一个整数n

接下来n-1行,每行两个整数表示一条边

接下来一行一个整数m表示操作次数

接下来m行,每行两个整数分别表示操作类型和被操作节点

\(\color{#0066ff}{输出格式}\)

对每个询问操作输出相应的结果

\(\color{#0066ff}{输入样例}\)

5
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1

\(\color{#0066ff}{输出样例}\)

5
1

\(\color{#0066ff}{数据范围与提示}\)

对所有数据,\(1\leq n \leq 10^5\),\(1\leq m \leq 10^5\)

\(\color{#0066ff}{ 题解 }\)

容易想到,开两个LCT分别维护黑白两种颜色

然后修改颜色的时候,暴力cut相邻的边,link相邻的边

然而。。。存在一种东东叫菊花图。。。

显然很容易就被Hack掉了

正常LCT的题目中,如果有边权,我们肯定是边权转到点权上,这样才好维护

然而。。。本题就是与众不同,他要把点权转到边权上!

把每个点的点权转到它与父亲的边上,特别的,开一个0号节点,\(0-1\)存的是1的点权

然后询问的联通块即为所在联通块根的siz-1,注意,根的颜色跟其它点不同

因为根父亲的边不在这里!

因此仍然是LCT维护子树大小即可

对于改变颜色的问题,发现只需要断一条边即可

所以复杂度就保证了

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 1e5 + 10;
struct LCT {
protected:
struct node {
node *ch[2], *fa;
int siz, tot;
node(int siz = 0, int tot = 1): siz(siz), tot(tot) { ch[0] = ch[1] = fa = NULL; }
void upd() {
tot = siz + 1;
if(ch[0]) tot += ch[0]->tot;
if(ch[1]) tot += ch[1]->tot;
}
bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
bool isr() { return fa->ch[1] == this; }
}pool[maxn];
void rot(node *x) {
node *y = x->fa, *z = y->fa;
bool k = x->isr(); node *w = x->ch[!k];
if(y->ntr()) z->ch[y->isr()] = x;
(x->ch[!k] = y)->ch[k] = w;
(y->fa = x)->fa = z;
if(w) w->fa = y;
y->upd(), x->upd();
}
void splay(node *o) {
while(o->ntr()) {
if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa);
rot(o);
}
}
void access(node *x) {
for(node *y = NULL; x; x = (y = x)->fa) {
splay(x);
if(x->ch[1]) x->siz += x->ch[1]->tot;
if((x->ch[1] = y)) x->siz -= y->tot;
x->upd();
}
}
node *findroot(node *o) {
access(o), splay(o);
while(o->ch[0]) o = o->ch[0];
return splay(o), o;
}
public:
void link(int l, int r) {
node *x = pool + l, *y = pool + r;
access(x), splay(x);
x->fa = y;
access(y), splay(y);
y->siz += x->tot;
y->upd();
}
void cut(int l, int r) {
node *x = pool + l;
access(x), splay(x);
x->ch[0] = x->ch[0]->fa = NULL;
x->upd();
}
int query(int p) {
node *o = findroot(pool + p);
return o->ch[1]->tot;
}
}s[2];
struct node {
int to;
node *nxt;
node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
};
node *head[maxn];
int n, m, f[maxn], col[maxn];
void add(int from, int to) {
head[from] = new node(to, head[from]);
}
void dfs(int x, int fa) {
f[x] = fa;
s[1].link(x, fa);
for(node *i = head[x]; i; i = i->nxt)
if(i->to != fa)
dfs(i->to, x);
}
int main() {
n = in();
int x, y;
for(int i = 1; i <= n; i++) col[i] = 1;
for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
dfs(1, 0);
for(m = in(); m --> 0;) {
x = in(), y = in();
if(x == 0) printf("%d\n", s[col[y]].query(y));
if(x == 1) s[col[y]].cut(y, f[y]), s[col[y] ^= 1].link(y, f[y]);
}
return 0;
}

SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块的更多相关文章

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

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

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

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

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

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

  4. [QTree6]Query on a tree VI

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

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

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

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

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

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

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

  8. BZOJ 3637: Query on a tree VI LCT_维护子树信息_点权转边权_好题

    非常喜欢这道题. 点权转边权,这样每次在切断一个点的所有儿子的时候只断掉一条边即可. Code: #include <cstring> #include <cstdio> #i ...

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

随机推荐

  1. RabbitMQ 消息队列 安装及使用

    RabbitMQ 消息队列安装: linux版本:CentOS 7 安装第一步:先关闭防火墙 1.Centos7.x关闭防火墙 [root@rabbitmq /]# systemctl stop fi ...

  2. VxVM vxsnap ERROR V-5-1-0 Volume cannot be linked due to size/regionsize incompatibility

    在做vxsnap addmir时报错如下: #> vxsnap -g OLS_DATA_DG -b addmir OLS_DATA_ACC_P mirvol=OLS_DATA_ACC_SM1 V ...

  3. #pragma execution_character_set("utf-8")

    VC2010增加了“#pragma execution_character_set("utf-8")”,指示char的执行字符集是UTF-8编码. VS2010 设置 字符编码: ...

  4. to_date() 、to_char()、to_number的FMT格式

     元素  含义 结果:2018/01/12(周五) -     /    ,    .     ;    :  (6中不同分隔符) 分隔符         y  显示一位年份  8 yy  显示二位年 ...

  5. bootstrap媒体查询常用写法

    @media (max-width: 768px) { /*超小屏幕设备 手机*/ } @media (min-width: 768px) and (max-width: 992px) { /*小屏幕 ...

  6. 如何设置Win10文件资源管理器默认打开“这台电脑”

    摘录自:http://www.ithome.com/html/win10/126066.htm

  7. java字符编码转换研究(转)

    1. 概述 本文主要包括以下几个方面:编码基本知识,java,系统软件,url,工具软件等. 在下面的描述中,将以"中文"两个字为例,经查表可以知道其GB2312编码是" ...

  8. css知多少(8)——float上篇(转)

    1. 引言 对于我们所有的web前端开发人员,float是或者曾经一度是你最熟悉的陌生人——你离不开它,却整天承受着它所带给你的各种痛苦,你以为它很简单就那么一点知识,但却驾驭不了它各种奇怪的现象. ...

  9. PLSQL语法

    Procedural Language和SQL的结合体.通过增加变量.控制语句,使我们可以写些逻辑更加复杂的数据库操作 语句框架组成 declare – 可选 声明各种变量或游标的地方. begin ...

  10. strcmp()比较函数和strcasecmp()和strnatcmp()

    strcmp()的函数原型如下() int strcmp(string str1,string str2) 该函数需要两个进行比较的参数字符串,如果这两个字符串相等,该函数就返回0,如果按字典顺序st ...