洛谷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 ...
随机推荐
- cmd远程连接oracle数据库
- MyBatis映射文件1(增删改、insert获取自增主键值)
增删改 Mybatis为我们提供了<insert>.<update>.<delete>标签来对应增删改操作 在接口中写增删改的抽象方法 void addEmp(Em ...
- 关于IWMS后台登录问题总结
一.登录后台,点击登录无反应: 1.是因为网站文件夹没有权限,需要右击文件夹,将只读勾选去掉 2.在安全中加入Everyone对象. 二.登录后台后,左边显示不全,是因为会员权限不够,需要给权限.
- 老男孩python学习自修第十天【三元表达式与lambda表达式】
例如: 1.使用三元表达式给变量赋值 result = '空' if x == None else x 2.使用lambda定义函数 add = lambda x, y: x+y
- wget 下载网页
如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ wget --http-user=username --http-passwd=password http:/w ...
- 提示“Web打印服务CLodop未安装启动”的各种原因和解决方法
旧版提示:"CLodop云打印服务(localhost本地)未安装启动!"新版提示:"Web打印服务CLodop未安装启动,点击这里下载执行安装(若此前已安装过,可点这里 ...
- How to remove popup on boot on Windows 2003
Administrative Tools\Manage Your Server\Add or remove a role\Add or Remove Programs Local Computer P ...
- PCIE
---恢复内容开始--- 高速差分总线.串行总线 每一条PCIe链路中只能连接两个设备这两个设备互为是数据发送端和数据接收端.PCIe链路可以由多条Lane组成,目前PCIe链路×1.×2.×4.×8 ...
- linux利用CMakeLists编译cuda程序
文件目录: cudaTest |--utils.cu |--utils.h |--squaresum.cu |--squaresum.h |--test.cpp |--CMakeLists.txt 编 ...
- Web API 2 使用SSL
在Server上启用SSL 稍后我会想在IIS 7 上配置SSL,现在先往下看. 本地测试,您可以启用SSL的IIS Express Visual Studio.在属性窗口中,启用SSL设置为True ...