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 为根的子 ...
随机推荐
- HDU 6706 huntian oy(杜教筛 + 一些定理)题解
题意: 已知\(f(n,a,b)=\sum_{i=1}^n\sum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\mod 1e9+7\),\(n\leq1e9\),且 ...
- Inkscape 太慢
问题: 在画板上图像较多时, 会在粘贴 / 删除 时会陷入长时间的等待 解决: 最佳: Ubuntu上面的比windows上的快上几十倍, 测试比较, 感觉并不是Ubuntu上多用了GPU, 总之, ...
- Next.js Conf 2020
Next.js Conf 2020 Next.js Conf Ticket https://nextjs.org/conf Conf Schedule https://confs.tech/javas ...
- WebIDE All In One
WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...
- 如何取消一个 Ajax 请求
如何取消一个 Ajax 请求 jQuery XMLHttpRequest.abort() https://stackoverflow.com/questions/446594/abort-ajax-r ...
- skills share & free videos
skills share & free videos 技术分享 & 免费视频 https://www.infoq.cn/video/list WebAssembly https://w ...
- js 获取是否为闰年,以及各月的天数 & isLeapYear
js 获取是否为闰年,以及各月的天数 calendar utils isLeapYear const isLeapYear = (year) => { return (year % 4 === ...
- H5 & animation
H5 & animation https://m.tb.cn/h.VYB7BAx?sm=51fda6 UA checker webp image & css animation CDN ...
- 软件工程中的CI&CD
wiki 在软件工程中,CI/CD或CICD通常是指持续集成以及持续交付或持续部署的组合实践 持续集成 在软件工程中,持续集成(CI)是每天将所有开发人员的工作副本合并到共享主线中的一种做法.[1] ...
- java安全管理器SecurityManager
本文转载自java安全管理器SecurityManager 导语 这是一篇对Java安全管理器入门的文章,目的是简单了解什么是SecurityManager,对管理器进行简单配置,解决简单问题. 比如 ...