洛谷P2486 染色
LCT的一种姿势。
题意:给定一棵树。每次把一条路径上的点染成一种颜色,求一条路径上有多少段颜色。
解:
首先可以很轻易的用树剖解决,只不过代码量让人望而却步...
有一种难以想象的LCT做法...
记录每个点的颜色,修改用lazy tag
询问时把那一条链split出来,pushup的时候看当前点和前驱/后继的颜色是否相同。如果不同就sum++,表示有一条连接不同颜色点的边。
最后的sum就是连接不同颜色的点的边数,再加1就是段数了。
#include <cstdio>
#include <algorithm> const int N = ; int fa[N], s[N][], col[N], sum[N], lc[N], rc[N], S[N], Sp, tag[N];
bool rev[N]; inline bool no_root(int x) {
return (s[fa[x]][] == x) || (s[fa[x]][] == x);
} inline void pushdown(int x) {
int ls = s[x][], rs = s[x][];
if(rev[x]) {
if(ls) {
rev[ls] ^= ;
std::swap(lc[ls], rc[ls]);
}
if(rs) {
rev[rs] ^= ;
std::swap(lc[rs], rc[rs]);
}
std::swap(s[x][], s[x][]);
rev[x] = ;
}
if(tag[x]) {
int c = tag[x];
if(ls) {
tag[ls] = col[ls] = lc[ls] = rc[ls] = c;
sum[ls] = ;
}
if(rs) {
tag[rs] = col[rs] = lc[rs] = rc[rs] = c;
sum[rs] = ;
}
tag[x] = ;
}
return;
} inline void pushup(int x) {
int ls = s[x][], rs = s[x][];
pushdown(ls);
pushdown(rs);
sum[x] = sum[ls] + sum[rs];
if(ls) {
lc[x] = lc[ls];
if(rc[ls] != col[x]) {
sum[x]++;
}
}
else {
lc[x] = col[x];
}
if(rs) {
rc[x] = rc[rs];
if(lc[rs] != col[x]) {
sum[x]++;
}
}
else {
rc[x] = col[x];
}
return;
} inline void rotate(int x) {
int y = fa[x];
int z = fa[y];
bool f = (s[y][] == x); fa[x] = z;
if(no_root(y)) {
s[z][s[z][] == y] = x;
}
s[y][f] = s[x][!f];
if(s[x][!f]) {
fa[s[x][!f]] = y;
}
s[x][!f] = y;
fa[y] = x; pushup(y);
pushup(x);
return;
} inline void splay(int x) {
int y = x;
S[++Sp] = y;
while(no_root(y)) {
y = fa[y];
S[++Sp] = y;
}
while(Sp) {
pushdown(S[Sp]);
Sp--;
} y = fa[x];
int z = fa[y];
while(no_root(x)) {
if(no_root(y)) {
(s[z][] == y) ^ (s[y][] == x) ?
rotate(x) : rotate(y);
}
rotate(x);
y = fa[x];
z = fa[y];
}
return;
} inline void access(int x) {
int y = ;
while(x) {
splay(x);
s[x][] = y;
pushup(x);
y = x;
x = fa[x];
}
return;
} inline void make_root(int x) {
access(x);
splay(x);
rev[x] = ;
return;
} inline int find_root(int x) {
access(x);
splay(x);
while(s[x][]) {
x = s[x][];
pushdown(x);
}
return x;
} inline void link(int x, int y) {
make_root(x);
fa[x] = y;
return;
} inline void cut(int x, int y) {
make_root(x);
access(y);
splay(y);
fa[x] = s[y][] = ;
pushup(y);
return;
} inline void change(int x, int y, int c) {
make_root(x);
access(y);
splay(y);
tag[y] = col[y] = lc[y] = rc[y] = c;
sum[y] = ;
return;
} inline int ask(int x, int y) {
make_root(x);
access(y);
splay(y);
return sum[y] + ;
} char str[]; int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d", &col[i]);
lc[i] = rc[i] = col[i];
}
for(int i = , x, y; i < n; i++) {
scanf("%d%d", &x, &y);
link(x, y);
} for(int i = , x, y, z; i <= m; i++) {
scanf("%s%d%d", str, &x, &y);
if(str[] == 'C') {
scanf("%d", &z);
change(x, y, z);
}
else {
int t = ask(x, y);
printf("%d\n", t);
}
} return ;
}
AC代码
有个简化版的问题:给定根,每次修改/询问必有一端点是根。有一种解法是,染色access,查询就看要跳多少个虚边。但是这样会被链卡成n²...不知道怎么改进。
洛谷P2486 染色的更多相关文章
- 洛谷 [P2486] 染色
树剖+线段树维护连续相同区间个数 注意什么时候长度要减一 #include <iostream> #include <cstdio> #include <cstdlib& ...
- 洛谷 P2486 BZOJ 2243 [SDOI2011]染色
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告
[SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...
- 洛谷 P2486 [SDOI2011]染色 LCT
Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...
- 洛谷 P2486 [SDOI2011]染色
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
- 洛谷P2486 [SDOI2011]染色
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
随机推荐
- RPC框架-RMI、RPC和CORBA的区别
关键词:RMI RPC CORBA简 介:本篇文章重点阐述RMI,附带介绍RPC和CORBA Java远程方法调用(Java RMI)是一组实现了远程方法调用(rmi)的API. java RMI是远 ...
- SpringBoot 中 JPA 的使用
详细连接 简书https://www.jianshu.com/p/c14640b63653 新建项目,增加依赖 在 Intellij IDEA 里面新建一个空的 SpringBoot 项目.具体步骤参 ...
- python爬虫scrapy之scrapy终端(Scrapy shell)
Scrapy终端是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码. 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码. ...
- springboot No Identifier specified for entity的解决办法
今天在做一个项目的时候遇到一个问题,实体类忘了指定主键id,然后报如下错误,也是自己粗心大意造成的,在此记录下. java.lang.IllegalStateException: Failed to ...
- Redis五大数据类型
首先说明下,Redis是:单线程+多路IO复用技术!!! string set > key + zset list hash 常用的几个命令: >keys * 查 ...
- rsync: chgrp "/.hosts.NBCxBB" (in test) failed: Operation not permitted (1)
#记一次rsync出现的错误(网上基本都是说权限问题) #这并不是权限的问题,应为实际的文件已经传过去了,但是rsync就是会报这个错误,(虽然使用是正常的,但是看着就是不爽) [root@local ...
- dreamweavercs 和dreamweaver cc的區別
https://zhidao.baidu.com/question/1541178469432885667.html
- hibernate主配置文件的配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuratio ...
- [离散时间信号处理学习笔记] 9. z变换性质
z变换描述 $x[n] \stackrel{\mathcal{Z}}{\longleftrightarrow}X(z) ,\quad ROC=R_x$ 序列$x[n]$经过z变换后得到复变函数$X(z ...
- 提高网络灵活性和效率的组网方式—SD-WAN
导读 最初,大多数企业只是简单地将软件覆盖添加到广域网连接上.但是,随着时间的推移,由于SD-WAN架构的易配置功能,企业将开始采用SD-WAN更复杂的功能. 广域网一般用于连接多个业务地点,如总部和 ...