BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】
一 题目
[SDOI2011]染色
二 分析
感觉树链剖分的这些题真的蛮考验码力的,自己的码力还是不够啊!o(╯□╰)o
还是比较常规的树链剖分,但是一定记得这里的线段树在查询的时候一定要考虑链于链相邻的两个点。
一开始自己已经把很多坑都已经注意了,包括颜色可以为0,链的相邻点,但怎么就是不正确,还是要多刷题。
三 AC代码
1 /************************************************************** 2 Problem: 2243 3 User: Dybala21 4 Language: C++ 5 Result: Accepted 6 Time:6652 ms 7 Memory:18580 kb 8 ****************************************************************/ 9 10 #include <bits/stdc++.h> 11 using namespace std; 12 const int MAXN = 1e5 + 15; 13 int n, m; 14 int c[MAXN]; 15 struct Edge 16 { 17 int to, next; 18 }edge[MAXN<<1]; 19 int head[MAXN], tot; 20 int e[MAXN][2]; 21 int fa[MAXN], deep[MAXN], sz[MAXN], son[MAXN]; 22 int p[MAXN], top[MAXN]; 23 int pos; 24 25 void init() 26 { 27 tot = 0, pos = 0; 28 memset(head, -1, sizeof(head)); 29 memset(son, -1, sizeof(son)); 30 } 31 void addedge(int u, int v) 32 { 33 edge[tot].to = v; 34 edge[tot].next = head[u]; 35 head[u] = tot++; 36 } 37 void dfs1(int u, int pre, int d) 38 { 39 fa[u] = pre; 40 sz[u] = 1; 41 deep[u] = d; 42 for(int i = head[u]; i != -1; i = edge[i].next) 43 { 44 int v = edge[i].to; 45 if(v != pre) 46 { 47 dfs1(v, u, d + 1); 48 sz[u] += sz[v]; 49 if(son[u] == -1 || sz[v] > sz[son[u]]) 50 son[u] = v; 51 } 52 } 53 } 54 void dfs2(int u, int sp) 55 { 56 p[u] = ++pos; 57 top[u] = sp; 58 if(son[u] != -1) 59 dfs2(son[u], sp); 60 else 61 return; 62 for(int i = head[u]; i != -1; i = edge[i].next) 63 { 64 int v = edge[i].to; 65 if(v != fa[u] && v != son[u]) 66 dfs2(v, v); 67 } 68 } 69 int lca(int x, int y) 70 { 71 int f1 = top[x], f2 = top[y]; 72 while(f1 != f2) 73 { 74 75 if(deep[f1] < deep[f2]) 76 { 77 swap(f1, f2); 78 swap(x, y); 79 } 80 x = fa[f1]; 81 f1 = top[x]; 82 } 83 if(deep[x] < deep[y]) swap(x, y); 84 return y; 85 } 86 struct Node 87 { 88 int l, r; 89 int lc, rc; 90 int lazy, sum; 91 }segTree[MAXN*3]; 92 void pushdown(int rt) 93 { 94 int tmp = segTree[rt].lazy; 95 segTree[rt].lazy = -1; 96 if(tmp == -1 || segTree[rt].l == segTree[rt].r) 97 return; 98 segTree[rt<<1].lc = segTree[rt<<1].rc = tmp; 99 segTree[rt<<1|1].lc = segTree[rt<<1|1].rc = tmp; 100 segTree[rt<<1].sum = segTree[rt<<1|1].sum = 1; 101 segTree[rt<<1].lazy = segTree[rt<<1|1].lazy = tmp; 102 } 103 void maintain(int rt) 104 { 105 segTree[rt].sum = segTree[rt<<1].sum + segTree[rt<<1|1].sum; 106 if(segTree[rt<<1].rc == segTree[rt<<1|1].lc) 107 segTree[rt].sum--; 108 segTree[rt].lc = segTree[rt<<1].lc; 109 segTree[rt].rc = segTree[rt<<1|1].rc; 110 } 111 void build(int rt, int l, int r) 112 { 113 segTree[rt].l = l; 114 segTree[rt].r = r; 115 segTree[rt].lazy = -1; 116 segTree[rt].sum = 0; 117 if(l == r) 118 return; 119 int mid = (l + r) >> 1; 120 build(rt<<1, l, mid); 121 build(rt<<1|1, mid + 1, r); 122 } 123 void update(int rt, int l, int r, int val) 124 { 125 pushdown(rt); 126 if(segTree[rt].l == l && segTree[rt].r == r) 127 { 128 segTree[rt].lazy = val; 129 segTree[rt].lc = segTree[rt].rc = val; 130 segTree[rt].sum = 1; 131 return; 132 } 133 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 134 if(r <= mid) 135 update(rt<<1, l, r, val); 136 else if(l > mid) 137 update(rt<<1|1, l, r, val); 138 else 139 { 140 update(rt<<1, l, mid, val); 141 update(rt<<1|1, mid+1, r, val); 142 } 143 maintain(rt); 144 } 145 void update(int x, int y, int val) 146 { 147 while(top[x] != top[y]) 148 { 149 if(deep[top[x]] < deep[top[y]]) 150 swap(x, y); 151 update(1, p[top[x]], p[x], val); 152 x = fa[top[x]]; 153 } 154 if(deep[x] < deep[y]) 155 swap(x, y); 156 update(1, p[y], p[x], val); 157 } 158 int query(int rt, int l, int r) 159 { 160 pushdown(rt); 161 if(segTree[rt].l == l && segTree[rt].r == r) 162 return segTree[rt].sum; 163 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 164 int ans = 0; 165 if(r <= mid) 166 ans += query(rt<<1, l, r); 167 else if(l > mid) 168 ans += query(rt<<1|1, l, r); 169 else 170 { 171 ans += query(rt<<1, l, mid); 172 ans += query(rt<<1|1, mid + 1, r); 173 if(segTree[rt<<1].rc == segTree[rt<<1|1].lc) 174 ans--; 175 } 176 return ans; 177 } 178 int find(int rt, int x) 179 { 180 pushdown(rt); 181 if(segTree[rt].l == segTree[rt].r) 182 return segTree[rt].lc; 183 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 184 if(x <= mid) 185 return find(rt<<1, x); 186 else 187 return find(rt<<1|1, x); 188 } 189 int query(int x, int y) 190 { 191 int res = 0; 192 while(top[x] != top[y]) 193 { 194 if(deep[top[x]] < deep[top[y]]) 195 swap(x, y); 196 res += query(1, p[top[x]], p[x]); 197 if(find(1, p[top[x]]) == find(1, p[fa[top[x]]])) 198 res--; 199 x = fa[top[x]]; 200 } 201 if(deep[x] < deep[y]) 202 swap(x, y); 203 res += query(1, p[y], p[x]); 204 return res; 205 } 206 int main() 207 { 208 //freopen("in.txt", "r", stdin); 209 init(); 210 scanf("%d%d", &n, &m); 211 for(int i = 1; i <= n; i++) 212 scanf("%d", &c[i]); 213 for(int i = 0; i < n - 1; i++) 214 { 215 scanf("%d%d", &e[i][0], &e[i][1]); 216 addedge(e[i][0], e[i][1]); 217 addedge(e[i][1], e[i][0]); 218 } 219 dfs1(1, 1, 1); 220 dfs2(1, 1); 221 build(1, 1, pos); 222 for(int i = 1; i <= n; i++) 223 update(1, p[i], p[i], c[i]); 224 char op; 225 int a, b, val; 226 for(int i = 0; i < m; i++) 227 { 228 scanf(" %c %d %d", &op, &a, &b); 229 if(op == 'Q') 230 { 231 printf("%d\n", query(a, b)); 232 } 233 else 234 { 235 scanf("%d", &val); 236 update(a, b, val); 237 } 238 } 239 return 0; 240 } 241
转载于:https://www.cnblogs.com/dybala21/p/10850691.html
BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】相关推荐
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- 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 2 1 1 Q ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1153 Solved: 421 [Submit][Sta ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)
题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...
- CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)
题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...
- BZOJ4127Abs——树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- YbtOJ-染色计划【树链剖分,线段树,tarjan】
正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...
最新文章
- 理解Java字符串常量池与intern()方法
- [转]sleep和wait有什么区别
- Locations Section of OpenCascade BRep
- screen 断开 screen -r 不能进入断开的会话
- 程序员面试金典 - 面试题 05.01. 插入(位运算)
- android 页面无法点击,为什么点击不跳转到下一界面,哪位大神帮瞅瞅
- TensorFlow tf.feature_column
- 【渝粤教育】电大中专工程图学基础_1作业 题库
- TeaVM当前版本(0.7.0)还不支持传递字串参数
- LaTex笔记二:visio画图并保存为eps格式
- coreos_CoreOS简介
- Gmail邮件客户端pop3和smtp服务器配置
- C++11 std::mutex使用以及std::lock_guard自动解锁避免忘记解锁
- 复数基础——负数的虚数根,复共轭,复数加法、减法、乘法、除法_6
- 800个有趣句子帮你记忆7000个单词(1-400)
- linux下设置共享目录
- 2020 JAVA eclipse 中文汉化包 安装教程--傻瓜式操作
- sstream和strstream的用法
- scroll-view的描点跳转
- J - 【黄色】这题真的是模板题 (Gym - 102072J )(spfa)