题目链接

题解

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

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

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

比较考验代码能力

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. Servlet接口应用(开发servlet三种方式)

    参见 文库/java/javaEE全新学习教程2.2节 1.通过URL调用 2通过提交表单 3超链接 4 javascript写一个函数,调用这个函数 1,首先在工程的WebRoot文件夹下建立一个j ...

  2. 基于Nginx简单实现动静分离

    1.首先安装Nginx 2.在Nginx.conf文件中添加如下配置: server{ listen 80; server_name www.lf.com; location ~ (.jpg|.png ...

  3. zigbee之MAC地址发送

    TI cc2530在出厂时候每一个芯片都固化了一个唯一的8个字节的地址,MAC或者IEEE地址. 协调器模块的MAC地址为:0x00124B000716550F(注意自己的是多少!!) 终端的MAC地 ...

  4. requests基础

    爬虫的基本原理:爬虫本质上是模拟人浏览信息的过程,只不过他通过计算机来达到快速抓取筛选信息的目的.所以我们想要写一个爬虫,最基本的就是要将我们需要抓取信息的网页原原本本的抓取下来.这个时候就要用到re ...

  5. 观察者(Observer)模式 * 委托事件

    观察者(Observer)模式:定义了一种一对多的依赖关系.让多个观察者对象同时监听某一个主题对象.   这个主题对象发生变化时会通知所有观察者对象,使他们字段更新自己 /* * 抽象主题(Subje ...

  6. asp.net 设置分页

    private const int PAGESIZE = 5; //定义每页有五行数据 private void FillPageList() { int pageCount = 0; // page ...

  7. 在C#中使用科大讯飞Web API进行语音合成

    最近工作中需要用到讯飞语音合成接口,网上看了下基本都是Java,PHP,Python版本的,正好补上C# 版本,代码比较简单.  首先在讯飞开放平台上创建一个WebApi项目,取到APPID与APIK ...

  8. java -jar jar包,运行报错没有主清单和无法加载主类

    jar: 包名(class 文件) META-INF(MANIFEST.MF ) .classpath 1.从eclipse直接导出的jar包: 2.修改MANIFEST.MF文件:

  9. 【bzoj1022】[SHOI2008]小约翰的游戏John 博弈论

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取 的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不 ...

  10. 八大排序算法的python实现(七)基数排序

    代码: #coding:utf-8 #author:徐卜灵 import math #print math.ceil(3.2) 向上取整4.0 #print math.floor(3.2) 向下取整3 ...