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 染色的更多相关文章

  1. 洛谷 [P2486] 染色

    树剖+线段树维护连续相同区间个数 注意什么时候长度要减一 #include <iostream> #include <cstdio> #include <cstdlib& ...

  2. 洛谷 P2486 BZOJ 2243 [SDOI2011]染色

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...

  3. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  4. 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告

    [SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...

  5. 洛谷 P2486 [SDOI2011]染色 LCT

    Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...

  6. 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...

  7. 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)

    题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...

  8. 洛谷 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 ...

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

随机推荐

  1. Angular MVC

    <!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...

  2. Hbase数据表解析

    demo为表的命名空间,user为表的名字you2个列族,一个为b.一个为o. NAME 为列族名,Replication_SCOPE实现一个远程集群的复制.compression数据压缩的类型 Hb ...

  3. 使用synchronized 实现ReentrantLock(美团面试题目)

    刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的. 方式一: public synchroni ...

  4. lr分布式测试--笔记

    LR 架构: controller做测试控制 scenario做测试场景的控制 vuser模拟用户和 load generator做负载产生 通过MI listener 跨防火墙监听 来实现分布式测试 ...

  5. linux寻找依赖文件

    在linux下编译安装软件有时候会遇到依赖文件找不到的情况,很多时候可以通过 sudo apt install -f 来解决:实在找不到怎么办,还有一个绝招可以用: 安装  apt-file sudo ...

  6. The Bug and Exception of Hibernate

    1: hibernate4.3.5 的@oneToOne注解有Bug,建议不使用该版本,或者使用该版本不使用@table   annotation. 2:今天在用hibernate4.2.13的时候, ...

  7. js的常用文档对象,document

    1.document的概念:window的子对象,由于DOM对象模型的默认对象就是window,因此Window对象中的方法和子对象不需要通过Window来引用. - 2.document的组成:属性 ...

  8. Draw your Next App Idea with Ink to Code

    Imagine that you’ve just been struck by inspiration for your next great app. You might start by jott ...

  9. luogu3391

    P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转 ...

  10. loj6270

    #6270. 数据结构板子题 sol:对于一个询问L,R,Limit,答案就是所有长度小于R-l+1的线段-长度小于Limit的线段-左端点在L左边的线段-右端点在R右边的线段,求这个东西 后面两个东 ...