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 为根的子 ...
随机推荐
- c# App.xaml
随着wpf自动创建的,是项目的起始点..Net先再App里找,找到了window然后开启window,项目真正的起始点是在App里. 这两个 (App 的xaml和cs文件)和MainWindow 的 ...
- Bootstrap巨幕
这是一个轻量.灵活的组件,它能延伸至整个浏览器视口来展示网站上的关键内容. jumbotron修饰 <div class="jumbotron"> <h1> ...
- springboot demo(一)快速开始
快速入门 maven构建项目 1.访问http://start.spring.io/ 2.选择构建工具Maven Project.Spring Boot版本2.26以及一些工程基本信息,点击" ...
- 三、mysql主从复制
1 MySQL 主从复制 1.1 主从复制的含义 在 MySQL 多服务器的架构中,至少要有一个主节点(master),跟主节点相对的,我们把它叫做从节点(slave). 主从复制,就是把主节点的数据 ...
- sdut2879 枚举起点DP
这个题和乌龟棋之类的DP差不多要学会缩减状态 就是,,我们只需枚举当前这个人是谁,选什么颜色,A用了多少,B用了多少 C用了多少我们就不用枚举了,知道选了多少人,A,B用了多少,你还不知C用了多少么, ...
- 快速计算类似斐波那契数列数列的数列的第N项,矩阵快速幂
这个题有循环节,可以不用这么做,这个可以当一个模板 #include <iostream> #include <cstdio> using namespace std; typ ...
- git 取消未成功的 merge
git 取消未成功的 merge # 合并时遇到冲突想取消操作,恢复index $ git merge --abort # 可以回退到某个提交 $ git reset --hard # 可以撤销某个提 ...
- Vue Component Registration All In One
Vue Component Registration All In One Vue 注册自定义组件 <template> <div class="back-to-top-c ...
- nasm win x86 hello world
hello.asm: extern MessageBoxA extern ExitProcess section .data title db "caption.",0 messa ...
- 阿里面试这样问:redis 为什么把简单的字符串设计成 SDS?
2021开工第一天,就有小伙伴私信我,还给我分享了一道他面阿里的redis题(这家伙绝比已经拿到年终奖了),我看了以后觉得挺有意思,题目很简单,是那种典型的似懂非懂,常常容易被大家忽略的问题.这里整理 ...