洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接
题解
比较裸的树链剖分 好像树链剖分的题都很裸
线段树中维护一个区间最左和最右的颜色,和答案
合并判断一下中间一段就可以了
比较考验代码能力
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
inline int gi() {
int f = 1, s = 0;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -1, c = getchar();
while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
return f == 1 ? s : -s;
}
const int N = 100010;
struct node {
int to, next;
}g[N<<1];
int last[N], gl;
inline void add(int x, int y) {
g[++gl] = (node) {y, last[x]};
last[x] = gl;
g[++gl] = (node) {x, last[y]};
last[y] = gl;
return ;
}
int c[N];
struct Segment_tree {
int l, r, v, lazy;
}t[N<<2];
int fa[N], siz[N], son[N], cnt, s[N], top[N], id[N], dep[N];
void dfs1(int u, int f) {
siz[u] = 1; fa[u] = f;
int MAX = 0;
for (int i = last[u]; i; i = g[i].next) {
int v = g[i].to;
if (v == f) continue;
dep[v] = dep[u]+1;
dfs1(v, u);
siz[u] += siz[v];
if (MAX < siz[v]) MAX = siz[v], son[u] = v;
}
return ;
}
void dfs2(int u, int topf) {
top[u] = topf;
s[++cnt] = c[u];
id[u] = cnt;
if (!son[u]) return ;
dfs2(son[u], topf);
for (int i = last[u]; i; i = g[i].next) {
int v = g[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
return ;
}
#define mid ((l+r)>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
void pushup(int rt) {
t[rt].l = t[ls].l; t[rt].r = t[rs].r;
t[rt].v = t[ls].v + t[rs].v;
if (t[ls].r == t[rs].l) t[rt].v--;
return ;
}
void build(int rt, int l, int r) {
if (l == r) {
t[rt] = (Segment_tree) {s[l], s[l], 1, 0};
return ;
}
build(ls, l, mid); build(rs, mid+1, r);
pushup(rt);
return ;
}
void pushdown(int rt) {
int lazy = t[rt].lazy;
t[rt].lazy = 0;
if (lazy) {
t[rs].lazy = t[ls].lazy = lazy;
t[rs].l = t[rs].r = t[ls].l = t[ls].r = lazy;
t[rs].v = t[ls].v = 1;
}
return ;
}
void update(int rt, int l, int r, int L, int R, int k) {
if (L <= l && r <= R) {
t[rt].v = 1;
t[rt].lazy = t[rt].l = t[rt].r = k;
return ;
}
pushdown(rt);
if (L <= mid) update(ls, l, mid, L, R, k);
if (R > mid) update(rs, mid+1, r, L, R, k);
pushup(rt);
return ;
}
struct zzy {
int l, r, v;
};
zzy merge(zzy a, zzy b) {
if (!a.v) return b;
if (!b.v) return a;
return (zzy) {a.l, b.r, a.v+b.v-(a.r == b.l)};
}
zzy query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R)
return (zzy) {t[rt].l, t[rt].r, t[rt].v};
zzy z = (zzy) {0, 0, 0};
pushdown(rt);
if (L <= mid)
z = query(ls, l, mid, L, R);
if (R > mid)
z = merge(z, query(rs, mid+1, r, L, R));
return z;
}
void upway(int x, int y, int z) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, 1, cnt, id[top[x]], id[x], z);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
update(1, 1, cnt, id[x], id[y], z);
return ;
}
int qway(int x, int y) {
zzy zx, zy;
zx = zy = (zzy) {0, 0, 0};
while (top[x] != top[y]) {
if (dep[top[x]] >= dep[top[y]]) {
zx = merge(query(1, 1, cnt, id[top[x]], id[x]), zx);
x = fa[top[x]];
}
else {
zy = merge(query(1, 1, cnt, id[top[y]], id[y]), zy);
y = fa[top[y]];
}
}
if (dep[x] > dep[y]) swap(x, y), swap(zx, zy);
zy = merge(query(1, 1, cnt, id[x], id[y]), zy);
zx.v += zy.v;
if (zx.l == zy.l) zx.v--;
return zx.v;
}
int main() {
int n = gi(), m = gi();
for (int i = 1; i <= n; i++) c[i] = gi();
for (int i = 1; i < n; i++) add(gi(), gi());
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
while (m--) {
char c; cin>>c;
if (c == 'C') {
int x = gi(), y = gi(), z = gi();
upway(x, y, z);
}
else {
int x = gi(), y = gi();
printf("%d\n", qway(x, y));
}
}
return 0;
}
洛谷 P2486 [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路径上所有点都染成 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- 2243: [SDOI2011]染色 树链剖分+线段树染色
给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 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 ...
随机推荐
- 598. Range Addition II 矩阵的范围叠加
[抄题]: Given an m * n matrix M initialized with all 0's and several update operations. Operations are ...
- Cloudstack动态修改CPU、内存
环境: CentOS6.4+Cloudstack4.2+xenserver 6.2 动态修改Cloudstack guest 内存.CPU 准备工作: 1.安装 xenserver tools工具包 ...
- scrapy设置代理
在爬取网站内容的时候,最常遇到的问题是:网站对IP有限制,会有防抓取功能,最好的办法就是IP轮换抓取(加代理) 下面来说一下Scrapy如何配置代理,进行抓取 1.在Scrapy工程下新建“middl ...
- 第十三课 Actionlib(2)
上节课讲到了客户端,这节课讲解一下服务器 1.创建服务器源文件touch fibonacciserver.cpp 2.编写源文件 3.修改CMakeLists.txt 4.编译之catkin_make ...
- Mybatis XML 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...
- idea无法下载源码(Cannot download sources)
有网上说,在命令行项目根目录下,执行如下命令下载: mvn dependency:resolve -Dclassifier=sources 我试着没有效果. 但是在本地仓库中,找到要下载的目录,删除以 ...
- Network in Network(NiN)
- Mlpconv layer with "micronetwork" with each conv layer to compute more abstract features ...
- Deep Residual Learning for Image Recognition
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun Microsoft Research {kahe, v-xiangz, v-sh ...
- 编写高质量代码改善C#程序的157个建议——建议36:使用FCL中的委托声明
建议36:使用FCL中的委托声明 FCL中存在3类这样的委托声明,它们分别是:Action.Func.Predicate.尤其是在它们的泛型版本出来以后,已经能够满足我们在实际编码过程中的大部分需求. ...
- Newtonsoft.Json.Linq
var json = "{\"name\":\"ok1\",\"sex\":\"man\"}"; / ...