题目链接

题解

比较裸的树链剖分 好像树链剖分的题都很裸

线段树中维护一个区间最左和最右的颜色,和答案

合并判断一下中间一段就可以了

比较考验代码能力

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]染色(树链剖分+线段树)的更多相关文章

  1. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  3. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  4. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  5. 2243: [SDOI2011]染色 树链剖分+线段树染色

    给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...

  6. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  7. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  8. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  9. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  10. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

随机推荐

  1. RichEdit在Win8上乱码

    之前的一个项目中使用了RichEdit,发现在Win8中输入中文乱码,但是复制粘贴正常. 经过各种搜索调查,发现是msftedit.dll的问题,我在win7上找到msftedit.dll,将它拷贝到 ...

  2. django 1.8 官方文档翻译:13-12 验证器

    django 1.8 官方文档翻译:13-12 验证器 2015年09月20日 21:36:18 ApacheCN_飞龙 阅读数:639  https://blog.csdn.net/wizardfo ...

  3. 第二章启程前的认知准备,2.1Opencv官方例程引导与赏析

    1.在opencv安装目录下,可以找到opencv官方提供的示例代码,具体位于...\opencv\sources\samples目录下,如下所示 名为c的文件夹存放着opencv1.0等旧版本的示例 ...

  4. bootstrap实现嵌套列

    <!DOCTYPE html> <html> <head> <title>Bootstrap 实例 - 嵌套列</title> <li ...

  5. struts2 、mybatis 、easyui 分页

    rows page 控件自动提交这两个参数 pageSize number The page size. 10pageNumber number Show the page number when p ...

  6. 编写高质量代码改善C#程序的157个建议——建议17:多数情况下使用foreach进行循环遍历

    建议17:多数情况下使用foreach进行循环遍历 由于本建议涉及集合的遍历,所以在开始讲解本建议之前,我们不妨来设想一下如何对结合进行遍历.假设存在一个数组,其遍历模式可以采用依据索引来进行遍历的方 ...

  7. delphi XE7 在Android编译SharedActivity时出错

    delphi XE6 在Android编译SharedActivity时正常,但xe7下编译出错,在uses添加Androidapi.Helpers就可以.

  8. 20145218PC平台逆向破解

    20145218PC平台逆向破解 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同 ...

  9. 关于eWebEditorAPI

    1.获取HTML document.getElementById(Iframe的名称).contentWindow.getHTML();在线API http://www.ewebeditor.net/ ...

  10. web集群时session同步的3种方法

    在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...