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 4497 GCD and LCM (非原创)
GCD and LCM Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total ...
- POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解
题意:给出n个字符,p个病毒串,要你求出长度为m的不包含病毒串的主串的个数 思路:不给取模最恶劣情况$50^{50}$,所以用高精度板子.因为m比较小,可以直接用DP写. 因为给你的串的字符包含拓展A ...
- HDU 4628 Pieces(状压DP)题解
题意:n个字母,每次可以删掉一组非连续回文,问你最少删几次 思路:把所有回文找出来,然后状压DP 代码: #include<set> #include<map> #includ ...
- OOP & 模块化, 多态, 封装
OOP 面向对象编程 (OOP) 是用抽象方式创建基于现实世界模型的一种编程模式.它使用先前建立的范例,包括模块化,多态和封装几种技术. 在 OOP 中,每个对象能够接收消息,处理数据和发送消息给其他 ...
- js & bitwise-operators
js & bitwise-operators 不用加减乘除运算符, 求整数的7倍 "use strict"; /** * * @author xgqfrms * @lice ...
- how to auto open a url in the browser by using terminal
how to auto open a url in the browser by using terminal Linux / MacOS # bash / zsh $ open http://loc ...
- 如何理解NGK的Layer2-侧链?
对于 NGK来说,Layer-2越来越重要,并成为共识.但是,"Layer-2" 是个不精确的标签.有些人说起 "Layer-2" 时,仅仅指的是 " ...
- NGK八大板块:为何郊区市场近来火爆?-VALAITIS, PETER ANTHONY分析
PAUL ADAMS ARCHITECT LTD董事长VALAITIS, PETER ANTHONY称受大环境影响很多纽约人都选择离开纽约市中心,搬往附近郊区,因此附近地区楼市开始不断升温. 根据房地 ...
- Power Query 合并数据
1 导入数据 合并数据 筛选字段 关闭并上载
- 在.NET中使用Apache Kafka(一)
曾经在你的应用程序中使用过异步处理吗?在处理不需要立即执行的任务时,异步代码似乎是不可避免的.Apache Kafka是最常用和最健壮的开源事件流平台之一.许多公司和开发者利用它的强大功能来创建高性 ...