SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块
\(\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维护颜色联通块的更多相关文章
- SP16549 QTREE6 - Query on a tree VI(LCT)
题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...
- 洛谷SP16549 QTREE6 - Query on a tree VI(LCT)
洛谷题目传送门 思路分析 题意就是要维护同色连通块大小.要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结. 至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次 ...
- 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$ 去暴力删边连 ...
- SPOJ QTREE6 Query on a tree VI 树链剖分
题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...
- bzoj3637 CodeChef SPOJ - QTREE6 Query on a tree VI 题解
题意: 一棵n个节点的树,节点有黑白两种颜色,初始均为白色.两种操作:1.更改一个节点的颜色;2.询问一个节点所处的颜色相同的联通块的大小. 思路: 1.每个节点记录仅考虑其子树时,假设其为黑色时所处 ...
- BZOJ 3637: Query on a tree VI LCT_维护子树信息_点权转边权_好题
非常喜欢这道题. 点权转边权,这样每次在切断一个点的所有儿子的时候只断掉一条边即可. Code: #include <cstring> #include <cstdio> #i ...
- 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 ...
随机推荐
- 对runtime的总结:让你会用Runtime
导语Runtime,简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制,是一套底层的纯C语言的API,我们平时所编写的OC代码,在程序的运行过程中都转成了runtime的代码,平时调方 ...
- mysql 回顾小练习
Student(id,sname,age,sex) 学生表 Course(id,cname,t_id) 课程表 SC(s_id,c_id,score) 成绩表 Teacher(id,Tname) 教师 ...
- 微信开发准备(一)--Maven仓库管理新建WEB项目
转自:http://www.cuiyongzhi.com/post/13.html 在我们的项目开发中经常会遇到项目周期很长,项目依赖jar包特别多的情况,所以我们经常会在项目中引入Maven插件,建 ...
- oracle 在xml中批量插入,批量修改及多组条件查询
最近公司用ibatis开发项目,本来可以用存储过程处理批量插入,批量修改及多组条件查询:但由于使用模块相对较小,暂时就在xml中配置,以前没有在xml做过类似处理,有必要记录一下:好了,代码如下: & ...
- jxl.read.biff.BiffException: Unable to recognize OLE stream异常
java代码读取excel文件时报: jxl.read.biff.BiffException: Unable to recognize OLE stream at jxl.read.biff.C ...
- C++深度解析教程学习笔记(2)C++中的引用
1.C++中的引用 (1)变量名的回顾 ①变量是一段实际连续存储空间的别名,程序中通过变量来申请并命名存储空间 ②通过变量的名字可以使用存储空间.(变量的名字就是变量的值,&变量名是取地址操作 ...
- python笔记--3--函数、生成器、装饰器、函数嵌套定义、函数柯里化
函数 函数定义语法: def 函数名([参数列表]): '''注释''' 函数体 函数形参不需要声明其类型,也不需要指定函数返回值类型 即使该函数不需要接收任何参数,也必须保留一对空的圆括号 括号后面 ...
- js 操作属性,操作内容,
disable=“disable” 让按钮变得不可选 先建一个按钮,让class = ’btn‘ 然后, 添加,修改属性 document.getElementsByClassName('btn')[ ...
- 算法Sedgewick第四版-第1章基础-1.4 Analysis of Algorithms-003定理
1. 2. 3. 4. 5. 6.
- ElementUI的表单和vee-validate结合使用时发生冲突的解决
在Vue项目中使用ElementUI表单时,同时又引入了vee-validate进行使用的时候,在浏览器上会出现这样的报错: [Vue warn]: The computed property &qu ...