洛谷P2486 染色
LCT的一种姿势。
题意:给定一棵树。每次把一条路径上的点染成一种颜色,求一条路径上有多少段颜色。
解:
首先可以很轻易的用树剖解决,只不过代码量让人望而却步...
有一种难以想象的LCT做法...
记录每个点的颜色,修改用lazy tag
询问时把那一条链split出来,pushup的时候看当前点和前驱/后继的颜色是否相同。如果不同就sum++,表示有一条连接不同颜色点的边。
最后的sum就是连接不同颜色的点的边数,再加1就是段数了。
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 100010; 5 6 int fa[N], s[N][2], col[N], sum[N], lc[N], rc[N], S[N], Sp, tag[N]; 7 bool rev[N]; 8 9 inline bool no_root(int x) { 10 return (s[fa[x]][0] == x) || (s[fa[x]][1] == x); 11 } 12 13 inline void pushdown(int x) { 14 int ls = s[x][0], rs = s[x][1]; 15 if(rev[x]) { 16 if(ls) { 17 rev[ls] ^= 1; 18 std::swap(lc[ls], rc[ls]); 19 } 20 if(rs) { 21 rev[rs] ^= 1; 22 std::swap(lc[rs], rc[rs]); 23 } 24 std::swap(s[x][0], s[x][1]); 25 rev[x] = 0; 26 } 27 if(tag[x]) { 28 int c = tag[x]; 29 if(ls) { 30 tag[ls] = col[ls] = lc[ls] = rc[ls] = c; 31 sum[ls] = 0; 32 } 33 if(rs) { 34 tag[rs] = col[rs] = lc[rs] = rc[rs] = c; 35 sum[rs] = 0; 36 } 37 tag[x] = 0; 38 } 39 return; 40 } 41 42 inline void pushup(int x) { 43 int ls = s[x][0], rs = s[x][1]; 44 pushdown(ls); 45 pushdown(rs); 46 sum[x] = sum[ls] + sum[rs]; 47 if(ls) { 48 lc[x] = lc[ls]; 49 if(rc[ls] != col[x]) { 50 sum[x]++; 51 } 52 } 53 else { 54 lc[x] = col[x]; 55 } 56 if(rs) { 57 rc[x] = rc[rs]; 58 if(lc[rs] != col[x]) { 59 sum[x]++; 60 } 61 } 62 else { 63 rc[x] = col[x]; 64 } 65 return; 66 } 67 68 inline void rotate(int x) { 69 int y = fa[x]; 70 int z = fa[y]; 71 bool f = (s[y][1] == x); 72 73 fa[x] = z; 74 if(no_root(y)) { 75 s[z][s[z][1] == y] = x; 76 } 77 s[y][f] = s[x][!f]; 78 if(s[x][!f]) { 79 fa[s[x][!f]] = y; 80 } 81 s[x][!f] = y; 82 fa[y] = x; 83 84 pushup(y); 85 pushup(x); 86 return; 87 } 88 89 inline void splay(int x) { 90 int y = x; 91 S[++Sp] = y; 92 while(no_root(y)) { 93 y = fa[y]; 94 S[++Sp] = y; 95 } 96 while(Sp) { 97 pushdown(S[Sp]); 98 Sp--; 99 } 100 101 y = fa[x]; 102 int z = fa[y]; 103 while(no_root(x)) { 104 if(no_root(y)) { 105 (s[z][1] == y) ^ (s[y][1] == x) ? 106 rotate(x) : rotate(y); 107 } 108 rotate(x); 109 y = fa[x]; 110 z = fa[y]; 111 } 112 return; 113 } 114 115 inline void access(int x) { 116 int y = 0; 117 while(x) { 118 splay(x); 119 s[x][1] = y; 120 pushup(x); 121 y = x; 122 x = fa[x]; 123 } 124 return; 125 } 126 127 inline void make_root(int x) { 128 access(x); 129 splay(x); 130 rev[x] = 1; 131 return; 132 } 133 134 inline int find_root(int x) { 135 access(x); 136 splay(x); 137 while(s[x][0]) { 138 x = s[x][0]; 139 pushdown(x); 140 } 141 return x; 142 } 143 144 inline void link(int x, int y) { 145 make_root(x); 146 fa[x] = y; 147 return; 148 } 149 150 inline void cut(int x, int y) { 151 make_root(x); 152 access(y); 153 splay(y); 154 fa[x] = s[y][0] = 0; 155 pushup(y); 156 return; 157 } 158 159 inline void change(int x, int y, int c) { 160 make_root(x); 161 access(y); 162 splay(y); 163 tag[y] = col[y] = lc[y] = rc[y] = c; 164 sum[y] = 0; 165 return; 166 } 167 168 inline int ask(int x, int y) { 169 make_root(x); 170 access(y); 171 splay(y); 172 return sum[y] + 1; 173 } 174 175 char str[10]; 176 177 int main() { 178 int n, m; 179 scanf("%d%d", &n, &m); 180 for(int i = 1; i <= n; i++) { 181 scanf("%d", &col[i]); 182 lc[i] = rc[i] = col[i]; 183 } 184 for(int i = 1, x, y; i < n; i++) { 185 scanf("%d%d", &x, &y); 186 link(x, y); 187 } 188 189 for(int i = 1, x, y, z; i <= m; i++) { 190 scanf("%s%d%d", str, &x, &y); 191 if(str[0] == 'C') { 192 scanf("%d", &z); 193 change(x, y, z); 194 } 195 else { 196 int t = ask(x, y); 197 printf("%d\n", t); 198 } 199 } 200 201 return 0; 202 }
AC代码
有个简化版的问题:给定根,每次修改/询问必有一端点是根。有一种解法是,染色access,查询就看要跳多少个虚边。但是这样会被链卡成n²...不知道怎么改进。
转载于:https://www.cnblogs.com/huyufeifei/p/10170584.html
洛谷P2486 染色相关推荐
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P2486 [SDOI2011]染色 LCT
Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...
- 染色(树链剖分 洛谷-P2486)
文章目录 题目描述 解析 代码 thanks for reading! 传送门 首先,对hash学姐对本题拔刀相助的debug行为表示衷心的感谢 题目描述 解析 用线段树维护颜色序列个数.最左颜色与最 ...
- 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
[题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...
- 洛谷P2486 lct做法
题意: 给出一颗nnn个结点的无根树,处理mmm个操作,每个操作只会是如下两种之一: (1)将结点aaa到bbb的路径上的所有点染成颜色kkk (2)询问结点aaa到结点bbb的简单路径的颜色段数量 ...
- 洛谷 - 试炼场(全部题目备份)
整理的算法模板合集: ACM模板 目录 1.新手村 1 - 1 洛谷的第一个任务 1 - 2 顺序与分支 1 - 3 循环!循环!循环! 1 - 4 数组 1 - 5 简单字符串 1 - 6 过程函数 ...
- [洛谷 P4084 USACO17DEC] Barn Painting G (树形dp经典)
[洛谷 P4084 USACO17DEC] Barn Painting G 题目链接 大致题意: 给定一颗N个节点组成的树,3种颜色,其中K个节点已染色,要求任意两相邻节点颜色不同,求合法染色方案数 ...
- 洛谷P4084 [USACO17DEC]Barn Painting G 题解
洛谷P4084 [USACO17DEC]Barn Painting G 题解 题目链接:P4084 [USACO17DEC]Barn Painting G 题意:题意:给定一颗N个节点组成的树,3种颜 ...
- 洛谷:P6062 [USACO05JAN]Muddy Fields G
题目链接:P6062 [USACO05JAN]Muddy Fields G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 此题重点在二分图的建图. 考虑放置木板的决策,由于可以重复 ...
最新文章
- apache和nginx的性能分析
- c++ gdi修改dpi_最新高血压标准修改,包括确诊标准和用药方案!你的药吃对了吗?...
- 修改Intellij IDEA中工程对应的Java SDK、Scala SDK
- C#获取键盘和鼠标操作的时间的类
- python查看对象占用内存_『Python』内存分析_List对象内存占用分析
- ethtool -g rx_魔兽怀旧服:黑G团避坑指南
- 传感器怎么获取障碍物的宽度信息_机器人感知 -- 测距传感器
- html的article标签,介绍一个html5做的网站,以及article标签的用法
- oracle bookauthor,Oracle 聚簇(征集)
- python 下采样和上采样
- How to research,22页PPT
- 机器学习:提升算法之Adaboost
- logistic模型预测人口python_基于python的logistic回归建模预测
- 物联网控制的智能LED灯带(1):WS2812灯带控制(WS2812/2811,ESP32,NODE-RED)
- 巨人综合音源优化版 – East West Quantum Leap Colossus Kontakt
- 使用多个路由器有线桥接实现无线漫游
- NOR Flash、NAND Flash和iNAND Flash的不同点
- 浅析Java的线程和Golang的协程
- html页面填充颜色,div填充颜色 怎么用css定义部分背景颜色
- 前后分离必备神器,YApi小白部署攻略