BZOJ_2243 [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
BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】的更多相关文章
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- B20J_2243_[SDOI2011]染色_树链剖分+线段树
B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...
- 2243: [SDOI2011]染色 树链剖分+线段树染色
给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- select(),fd_set(),fd_isset()
1. select函数 1. 用途 在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在 ...
- 007.NET5 Log4Net组件使用
NET 5 Log4Net组件使用 1. Nuget引入程序集:log4net + Microsfot.Extensions.Logging.Log4Net.AspNetCore 2. 准备配置文件 ...
- macOS 没有鼠标 怎么使用 快捷键
macOS 没有鼠标 怎么使用 快捷键 mini 链接蓝牙鼠标 菜单选择 光标聚焦 上下选择 确认,选中 用键盘浏览菜单 若要使用这些快捷键,请先按下 Control-F2 或 Fn-Control- ...
- chroot vs docker
chroot vs docker chroot Linux A chroot on Unix operating systems is an operation that changes the ap ...
- github & markdown & image layout
github & markdown & image layout css & right https://github.com/sindresorhus/log-symbols ...
- macOS & Nginx
macOS & Nginx ngnix # 使用 brew 安装(如果没有 brew 命令,需要自行安装 brew) $ brew install nginx $ nginx -h # 查看 ...
- NGK乘势而上打造生态所,建立全方位的区块链生态系统
当金融理财变成了生活的一部分,购买金融衍生品的眼光成为了影响生活质量重要组成部分.这是一个不缺少黄金的年代,一夜间实现财务自由的故事每天都在上演,但是由于太多人缺少发现黄金的眼睛,只能被财富和机遇拒之 ...
- 10月上线的NGK global有怎样的发展前景?
随着NGK global 10月份的上线时间将近,社区中也开始纷纷讨论.预测起NGK global上线后的表现,对此小编也有一些自己的理解,就此分享给大家. 在基于实体生态的赋能下,NGK globa ...
- NGK和USDN的应用
一.NGK和USDN的发展方向 目前区块链将会朝着两个方向去发展,第一种是金融经济的衍生品,第二种是商业应用,快速支付的货币体系,NGK.IO公链是基于分布式应用设计的商用金融区块链操作系统,通过数字 ...
- 【目标检测】用Fast R-CNN训练自己的数据集超详细全过程
目录: 一.环境准备 二.训练步骤 三.测试过程 四.计算mAP 寒假在家下载了Fast R-CNN的源码进行学习,于是使用自己的数据集对这个算法进行实验,下面介绍训练的全过程. 一.环境准备 我这里 ...